The Java EE 7 Tutorial
31.6 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:
@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:
GET /employee Accept: text/plain
This will produce the following response:
500 Oracle Parkway, Redwood Shores, CA
The getEmployeeAddressXml
method is called for an HTTP request that looks like the following:
GET /employee Accept: text/xml
This will produce the following response:
<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.
@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:
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:
[["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:
@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.