Thursday, June 10, 2010

Response objects and the use of GenericEntity class with RESTEasy

Recently during the implementation of a REST API, I wanted to return a complex response containing a list of objects (Patients). The issue was that the RESTEasy build-in JAXB MessageBodyWriter could not directly handle lists of JAXB objects (Java has trouble obtaining generic type information at runtime).

I was recently in a situation where I had to create a complex response to a HTTP POST for my REST API. I am using JAXB /JSON support from RESTEasy.

I found some element of answer in the book "RESTFul Java with JAX-RS" from Bill Burke (pp 102). However the code snippet had a couple of errors:

  • the GenericEntity object cannot be passed to the Response.ok() method directly (a ResponseBuilder is required).

  • references to GenericEntity needs to be parameterized.

My use case is a little more complex than in the book. I am receiving a user-name and password from a POST (e.g. a form submit). I then perform the authentication and returns a list of Patient objects in a JSON/GZIP compressed format (instead a list of Customer objects) together with an authentication token.





The resulting code looks like this:


   @POST
   @Path("/token")
   @Consumes("application/x-www-form-urlencoded")
   @Produces("application/json")
   @GZIP
   public Response getPatientsWithToken(@FormParam("username") String username, @FormParam("password") String password) {
  
        Login login = new Login(username, password);
        // ... perform authentication here ....
    
        // Build the returning patient list
        List<Patient> returnList = new ArrayList<Patient>();
        returnList.addAll(patients.values());
        Collections.sort(returnList);
      
        GenericEntity<List<Patient>> entity = new GenericEntity<List<Patient>>(returnList){};
      
        // Create the response
        ResponseBuilder builder = Response.ok(entity);
        return builder.build();
   }



Of course you will have to import the following classes as well:


import javax.ws.rs.core.GenericEntity;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;

3 comments:

Laurent said...

Thanks, exactly what I was looking for!
I wanted to return a Response Object for all my API calls (GenericEntity to the rescure for generic collections), so that I can return a custom Error Entity, in case something goes wrong..

Anonymous said...

It is of great help. Worked like a gem.

Anonymous said...

It is of great help. Worked like a gem.