Jersey Generic Type Marching

I need to return several results to the client list and the total number of results. I have to do this in several places with different objects, so I would like to have a common class with these two attributes:

@XmlRootElement public class QueryResult<T> implements Serializable { private int count; private List<T> result; public QueryResult() { } public void setCount(int count) { this.count = count; } public void setResult(List<T> result) { this.result = result; } public int getCount() { return count; } public List<T> getResult() { return result; } } 

And the service:

 @GET @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) public QueryResult<TestEntity> findAll( QueryResult<TestEntity> findAll = facade.findAllWithCount(); return findAll; } 

The essence is not important:

 @XmlRootElement public class TestEntity implements Serializable { ... } 

But this throws: javax.xml.bind.JAXBException: class test.TestEntity nor any of its super class is known to this context.

Returning only the collection is easy, but I don't know how to return my own generic type. I tried to use GenericType , but to no avail - I think this applies to collections.

+4
java jersey jaxb
Jun 06 2018-12-06T00:
source share
3 answers

I solved this with the @XmlSeeAlso annotation:

 @XmlSeeAlso(TestEntity.class) @XmlRootElement public class QueryResult<T> implements Serializable { ... } 

Another possibility is to use @XmlElementRefs .

+1
Jun 06 '12 at 8:25
source share

After fighting this, I found that the answer is quite simple. In your service, return the built-in GenericEntity answer ( http://docs.oracle.com/javaee/6/api/javax/ws/rs/core/GenericEntity.html ) typed accordingly. For example:

 @GET @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) public Response findAll(){ return Response.ok(new GenericEntity<TestEntity>(facade.findAllWithCount()){}).build(); } 

Check out this post about why you can't just return GenericEntity: GenericEntity jersey doesn't work

A more complicated solution would be to return the GenericEntity function directly and create your own XmlAdapter ( http://jaxb.java.net/nonav/2.2.4/docs/api/javax/xml/bind/annotation/adapters/XmlAdapter.html ) for handling marshalling / unmarshalling. However, I have not tried this, so this is just a theory.

+4
Feb 01 '13 at 12:08
source share

I had exactly the same problem. The problem is due to erasure of the Java type.

My first approach was to create a result class for each entity type:

 public class Entity1Result extends QueryResult<Entity1> { ... } public class Entity2Result extends QueryResult<Entity2> { ... } 

I returned a generic QueryResult<> in my settings for built-in types only, such as QueryResult<String> or QueryResult<Integer>

But it was cumbersome because I had many entities. So my other approach was to use only JSON, and I changed my class of results to non-generic and used the result field of Object :

 public class QueryResult { private Object result; } 

It works great, Jersey is able to serialize everything that I give it in JSON (Note: I do not know if this is important, but QueryResult and all my entities still have @Xml... annotations @Xml... for lists with their own entity types.

If you have problems with collections, you can also see this question.

+1
Jun 06 '12 at 7:19
source share



All Articles