Wednesday, July 08, 2009

Multiple representations of a REST Resource using JAX-RS

[Note: I have a post that provides an in-order list of all the JAX-RS and Jersey-related posts I've written. You may want to start at the beginning if you haven't already read the previous posts]

One of the principles of RESTful web services is that a client makes a request for a representation of a resource. The resource itself is an abstract notion, just as an object-oriented model of some real world object is an abstraction. But in the case of a RESTful web service, it becomes possible to return different kinds of information based upon what the client requests.

As a simple example, imagine we are aficionados of military planes and decide to create a web service which provides non-secret information (and perhaps speculation) about various military aircraft (thanks to my friend Bruce for this idea). In the REST world, our resource might be "F-22". In this case the resource is the United States F-22 fighter plane. But there are many possible representations of an F-22. We might provide a summary description of the plane, or an image of the plane, or a CAD schematic of the plane, or any of a number of other representations. This basic notion that a single resource may have more than representation can be demonstrated with a simple object that can provide either an HTML text description of the F-22 or a simple graphic drawing of the plane.

Perhaps the simplest way to provide more than one representation for a given resource is to provide two different methods in a Java class with different MIME types in their @Produces annotations. In our example, assume we have a class named F22 which provides representations of an F-22. It can have a method that returns HTML and a different method that returns a JPEG image. This is very easy to do with JAX-RS:

@Path("/planes/f22")
public class F22 {
@GET @Produces("text/html")
public String getHTMLRepresentation() throws IOException {
File f = new File( "F22.html");
BufferedReader br = new BufferedReader(new FileReader(f));
StringWriter sw = new StringWriter();
for( String s = br.readLine(); s != null ; s = br.readLine() ) {
sw.write( s );
sw.write( '\n' );
}
return sw.toString();
}

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

}

We now run into a problem using a web browser for a testing client. The browser is going to specify in it’s HTTP request the formats it prefers for a response. The browser doesn’t allow us to specify the type of representation we want. So, do we get back the HTML representation or the JPEG image? The answer depends upon the particular web browser you are using. Firefox 3.5 on a Mac and Windows and Safari on a Mac return the HTML form:



IE 6 on Windows and IE 8 on Windows return the JPEG image:



There are other ways to return more than on representation. For example, can have a single method which returns a JAX-RS Response object. That Response can have different contents depending upon the requested representation. I may explore these in future posts.

1 comment:

Rockhopper said...

Use curl to test instead of a browser.