Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Marshalling of generic types in Jersey

Tags:

java

jaxb

jersey

I need to return to client list of few results and total count of results. I have to do it on several places with different entities so I would like to have a generic 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;
}

Entity is not important:

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

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

Returning of just collection is easy but I don't know how to return my own generic type. I tried to use GenericType but without success - I think it's ment for collections.

like image 655
ziri Avatar asked Jun 06 '12 06:06

ziri


2 Answers

After battling with this myself I discovered the answer is fairly simple. In your service, return a built response of a GenericEntity (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();
}

See this post as to why you cannot simply return GenericEntity: Jersey GenericEntity Not Working

A more complex solution could be to return the GenericEntity directly and create your own XmlAdapter (http://jaxb.java.net/nonav/2.2.4/docs/api/javax/xml/bind/annotation/adapters/XmlAdapter.html) to handle marshalling/unmarshalling. I've not tried this, though, so it's just a theory.

like image 76
ndtreviv Avatar answered Sep 30 '22 08:09

ndtreviv


I solved it using @XmlSeeAlso annotation:

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

Another possibility is to use @XmlElementRefs.

like image 35
ziri Avatar answered Sep 30 '22 07:09

ziri