I found some strange behaviour that I cannot understand.
I have tested 4 similar examples:
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response produce() {
List<Book> books = Arrays
.asList(new Book[] {
new Book("aaa", "AAA", "12345"),
new Book("bbb", "BBB", "09876")
});
return Response.ok(books).build();
}
@GET
@Produces(MediaType.APPLICATION_JSON)
public List<Book> produce() {
List<Book> books = Arrays
.asList(new Book[] {
new Book("aaa", "AAA", "12345"),
new Book("bbb", "BBB", "09876")
});
return books;
}
@GET
@Produces(MediaType.APPLICATION_XML)
public List<Book> produce() {
List<Book> books = Arrays
.asList(new Book[] {
new Book("aaa", "AAA", "12345"),
new Book("bbb", "BBB", "09876")
});
return books;
}
@GET
@Produces(MediaType.APPLICATION_XML)
public Response produce() {
List<Book> books = Arrays
.asList(new Book[] {
new Book("aaa", "AAA", "12345"),
new Book("bbb", "BBB", "09876")
});
return Response.ok(books).build();
}
Everything works in #1, #2, #3 but 4th example throws:
Could not find MessageBodyWriter for response object of type: java.util.Arrays$ArrayList of media type: application/xml.
I run it on Wildfly 9 and I wonder if it is related to RestEasy or JaxRS in general? I know that I can fix it by wrapping collection in GenericEntity, but I don't understand this inconsistent behaviour.
The problem is the missing of type information. This is required for JAXB, which handles the XML serialization.
1 and 2 works because Jackson is being used for JSON, and it generally doesn't need to know type information as it just introspects properties.
3 works because type information is known through the method return type.
4 doesn't work because there is no type information. It's is erased by type erasure. That's where GenericEntity
comes to the rescue. It stores the type information.
Normally type erasure removes generic type information such that a
Response
instance that contains, e.g., an entity of typeList<String>
appears to contain a rawList<?>
at runtime. When the generic type is required to select a suitableMessageBodyWriter
, this class may be used to wrap the entity and capture its generic type.