type=page
status=published
title=Runtime Content Negotiation
next=jaxrs-advanced007.html
prev=jaxrs-advanced005.html
~~~~~~
Runtime Content Negotiation
===========================

[[GKQBQ]]

[[runtime-content-negotiation]]
Runtime Content Negotiation
---------------------------

The `@Produces` and `@Consumes` annotations handle static content
negotiation in JAX-RS. These annotations specify the content preferences
of the server. HTTP headers such as `Accept`, `Content-Type`, and
`Accept-Language` define the content negotiation preferences of the
client.

For more details on the HTTP headers for content negotiation, see HTTP
/1.1 - Content Negotiation
(`http://www.w3.org/Protocols/rfc2616/rfc2616-sec12.html`).

The following code snippet shows the server content preferences:

[source,oac_no_warn]
----
@Produces("text/plain")
@Path("/employee")
public class Employee {

    @GET
    public String getEmployeeAddressText(String address) {...}

    @Produces("text/xml")
    @GET
    public String getEmployeeAddressXml(Address address) {...}
}
----

The `getEmployeeAddressText` method is called for an HTTP request that
looks like the following:

[source,oac_no_warn]
----
GET /employee
Accept: text/plain
----

This will produce the following response:

[source,oac_no_warn]
----
500 Oracle Parkway, Redwood Shores, CA
----

The `getEmployeeAddressXml` method is called for an HTTP request that
looks like the following:

[source,oac_no_warn]
----
GET /employee
Accept: text/xml
----

This will produce the following response:

[source,oac_no_warn]
----
<address street="500 Oracle Parkway, Redwood Shores, CA" country="USA"/>
----

With static content negotiation, you can also define multiple content
and media types for the client and server.

[source,oac_no_warn]
----
@Produces("text/plain", "text/xml")
----

In addition to supporting static content negotiation, JAX-RS also
supports runtime content negotiation using the
`javax.ws.rs.core.Variant` class and `Request` objects. The `Variant`
class specifies the resource representation of content negotiation. Each
instance of the `Variant` class may contain a media type, a language,
and an encoding. The `Variant` object defines the resource
representation that is supported by the server. The
`Variant.VariantListBuilder` class is used to build a list of
representation variants.

The following code snippet shows how to create a list of resource
representation variants:

[source,oac_no_warn]
----
List<Variant> vs = Variant.mediatypes("application/xml", "application/json")
        .languages("en", "fr").build();
----

This code snippet calls the `build` method of the `VariantListBuilder`
class. The `VariantListBuilder` class is invoked when you call the
`mediatypes`, `languages`, or `encodings` methods. The `build` method
builds a series of resource representations. The `Variant` list created
by the `build` method has all possible combinations of items specified
in the `mediatypes`, `languages`, and `encodings` methods.

In this example, the size of the `vs` object as defined in this code
snippet is 4, and the contents are as follows:

[source,oac_no_warn]
----
[["application/xml","en"], ["application/json","en"],
    ["application/xml","fr"],["application/json","fr"]]
----

The `javax.ws.rs.core.Request.selectVariant` method accepts a list of
`Variant` objects and chooses the `Variant` object that matches the HTTP
request. This method compares its list of `Variant` objects with the
`Accept`, `Accept-Encoding`, `Accept-Language`, and `Accept-Charset`
headers of the HTTP request.

The following code snippet shows how to use the `selectVariant` method
to select the most acceptable `Variant` from the values in the client
request:

[source,oac_no_warn]
----
@GET
public Response get(@Context Request r) { 
    List<Variant> vs = ...;
    Variant v = r.selectVariant(vs);
    if (v == null) {
        return Response.notAcceptable(vs).build();
    } else {
        Object rep = selectRepresentation(v);
        return Response.ok(rep, v);
    }
}
----

The `selectVariant` method returns the `Variant` object that matches the
request or null if no matches are found. In this code snippet, if the
method returns null, a `Response` object for a nonacceptable response is
built. Otherwise, a `Response` object with an OK status and containing a
representation in the form of an `Object` entity and a `Variant` is
returned.


