Chapter 15. JAX-RS Content Negotiation
The HTTP protocol has built-in content negotiation headers that allow the client and server to specify the type of content that they transfer, and the type of content they prefer to receive. The server declares content preferences via the
@Produces
and @Consumes
headers.
@Consumes
is an array of media types that a particular resource or resource method consumes. For example:
@Consumes("text/*") @Path("/library") public class Library { @POST public String stringBook(String book) {...} @Consumes("text/xml") @POST public String jaxbBook(Book book) {...}
When a client makes a request, JAX-RS first locates all methods that match the path. It then sorts objects based on the content-type header sent by the client. If a client sends the following:
POST /library content-type: text/plain this is a nice book
The
stringBook()
method is invoked, because it matches the default text/*
media type. If the client sends XML, like so:
POST /library content-type: text/xml <book name="EJB 3.0" author="Bill Burke"/>
Then the
jaxbBook()
method is invoked.
@Produces
is used to map a client request and match it with the client's Accept
header. The Accept HTTP header is sent by the client, and defines the media types that the client prefers to receive from the server.
@Produces("text/*") @Path("/library") public class Library { @GET @Produces("application/json") public String getJSON() {...} @GET public String get() {...}
So, if the client sends:
GET /library Accept: application/json
The
getJSON()
method would be invoked.
@Consumes
and @Produces
can support multiple media types by presenting them in a list. The client's Accept
header can also list multiple media types to receive. More specific media types are selected first. The Accept
header (or @Produces
or @Consumes
) can also specify weighted preferences that will match requests with resource methods. (This is best explained in Section 14.1 of RFC 2616.) RESTEasy provides support for this more complex method of content negotiation.
An alternative method used by JAX-RS is a combination of media-type, content-language, and content encoding, in addition to etags, last modified headers, and other pre-conditions. This is a more complex form of content negotiation, performed programmatically by the application developer via the
javax.ws.rs.Variant
, VarianListBuilder
, and Request
objects. Request
is injected using the @Context
annotation. (For more information, read the JavaDoc.)