Thursday, July 09, 2009

JAX-RS Response Entity Providers


[Note: This is one in a series of posts about JAX-RS. You may wish to start at the beginning]

If you read my previous entry about returning more than one representation of a resource, you saw this sample code for a RESTful F-22 fighter plane resource:
@Path("/planes/f22/")
public class F22 {
@GET @Produces("text/html") @Path( "f22.html" )
public File getHTMLRepresentation() throws IOException {
return new File( "f22.html");
}

@GET @Produces("image/jpeg") @Path( "f22.jpg" )
public File getImageRepresentation() {
return new File( "f22.jpg");
}
}

These methods might seem a bit odd at first sight. The getHTMLRepresentation method has a @Produces annotation which indicates the method produces a MIME type of "text/html", but the return type of the Java method is java.io.File. Similarly, the getImageRepresentation method produces "image/jpeg" but the Java method also returns a File.

This apparent disconnect is resolved by a JAX-RS feature called entity providers. The specification states that entity providers "supply mapping services between representations and their associated Java types". The job of entity providers is to take HTTP request entities and turn them into Java objects on the request side, and take Java objects and turn them into response entities on the result side. Entity providers which convert request entities to Java types implement the MessageBodyReader interface and must be marked with the @Provider annotation. Similarly, entity providers which convert Java return types to response entities implement the MessageBodyWriter interface and are marked with the @Provider annotation (see Figure 1).


Figure 1: Conversion between HTTP entities and Java objects

JAX-RS mandates a set of built-in entity providers covering common entity types such as strings, input streams, java.io.Reader objects, java.io.File objects, and a number of other sophisticated types of conversions.

In this case, Jersey takes the returned File object and uses it’s contents as the response entity which it marks as “text/html”. This mapping from Java types to HTTP entities can be quite powerful, as you don’t have to write code to read the contents of files and return them as byte arrays, Strings, etc. It also offers a JAX-RS implementation the opportunity to implement handling of some types much more efficiently. For example, a JAX-RS implementation might choose to use Java’s NIO facilities to read the contents of a file for performance reasons.

This notion of entity providers is a crucial aid to the POJO (Plain Old Java Objects) style of JAX-RS applications, and avoids what would otherwise be a great deal of boilerplate code in the application performing these conversions.

1 comment:

Venkat Mantirraju said...

You did great amount of research. This is really helpful and it saves lots of boilerplate code. Appreciate your time and effort in this regard.