Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JAX-RS: How to automatically serialize a collection when returning a Response object?

I have a JAXB-annotated employee class:

@XmlRootElement(name = "employee")
public class Employee {

    private Integer id;
    private String name;

    ...

    @XmlElement(name = "id")
    public int getId() {
        return this.id;
    }

    ... // setters and getters for name, equals, hashCode, toString
}

And a JAX-RS resource object (I'm using Jersey 1.12)

@GET
@Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
@Path("/")
public List<Employee> findEmployees(
    @QueryParam("name") String name, 
    @QueryParam("page") String pageNumber,
    @QueryParam("pageSize") String pageSize) {
    ...
    List<Employee> employees = employeeService.findEmployees(...);

    return employees;
}

This endpoint works fine. I get

<employees>
  <employee>
    <id>2</id>
    <name>Ana</name>
  </employee>
</employees>

However, if I change the method to return a Response object, and put the employee list in the response body, like this:

@GET
@Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
@Path("/")
public Response findEmployees(
    @QueryParam("name") String name, 
    @QueryParam("page") String pageNumber,
    @QueryParam("pageSize") String pageSize) {
    ...
    List<Employee> employees = employeeService.findEmployees(...);

    return Response.ok().entity(employees).build();
}

the endpoint results in an HTTP 500 due to the following exception:

javax.ws.rs.WebApplicationException: com.sun.jersey.api.MessageException: A message body writer for Java class java.util.ArrayList, and Java type class java.util.ArrayList, and MIME media type application/xml was not found

In the first case, JAX-RS has obviously arranged for the proper message writer to kick in when returning a collection. It seems somewhat inconsistent that this doesn't happen when the collection is placed in the entity body. What approach can I take to get the automatic JAXB serialization of the list to happen when returning a response?

I know that I can

  • Just return the list from the resource method
  • Create a separate EmployeeList class

but was wondering whether there is a nice way to use the Response object and get the list to serialize without creating my own wrapper class.

like image 235
Ray Toal Avatar asked Aug 02 '12 05:08

Ray Toal


2 Answers

You can wrap the List<Employee> in an instance of GenericEntity to preserve the type information:

  • http://docs.oracle.com/javaee/6/api/javax/ws/rs/core/GenericEntity.html
like image 197
bdoughan Avatar answered Nov 16 '22 14:11

bdoughan


You can use GenericEntity to send the collection in the Response. You must have included appropriate marshal/unmarshal library like moxy or jaxrs-jackson.

Below is the code :

    @GET
    @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
    @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
    @Path("/")
    public Response findEmployees(
        @QueryParam("name") String name, 
        @QueryParam("page") String pageNumber,
        @QueryParam("pageSize") String pageSize) {
        ...
        List<Employee> employees = employeeService.findEmployees(...);

        GenericEntity<List<Employee>> entity = new GenericEntity<List<Employee>>(Lists.newArrayList(employees))

        return Response.ok().entity(entity).build();
    }
like image 4
Jitender Chahar Avatar answered Nov 16 '22 14:11

Jitender Chahar