Hello helpful Internet citizens
I'm getting to know the internals of Jersey and JAXB on Glassfish, and I've
run into a bit of a snag serializing a class that uses generics. I need to
return XML to an ExtJS paginated grid in the following format:
<countedCollection>
<totalCount>202</totalCount>
<record version="1">
<id>25</id>
<name>Test Client 1</name>
<baseTag>0025</baseTag>
<clientStatus>
<id>1</id>
<description>Active</description>
</clientStatus>
</record>
<record version="1">
<id>26</id>
<name>Test Client 2</name>
<baseTag>0026</baseTag>
<clientStatus>
<id>1</id>
<description>Active</description>
</clientStatus>
</record>
</countedCollection>
The names are fungible, but the imperative thing is that there be a total
record count and a list of records. JAXB serializes collections nicely
enough, and if I return a collection filled with JPA entities from a Jersey
@GET method, JAXB will serialize the collection, and then Jersey will
happily shuttle it across the wire. Rather than declare a new class for
each JPA type, I wrote the following class to encapsulate both the
collection and a total records count using generics:
package com.donotuse.facade;
import java.util.*;
import javax.xml.bind.annotation.*;
import com.donotuse.jpa.*;
@XmlRootElement
//_at_XmlSeeAlso({Client.class})
public class CountedCollection<T> {
private static final long serialVersionUID = -1483486849810154904L;
@XmlElement
private long totalCount;
@XmlElement
private Vector<T> records;
CountedCollection() {
}
CountedCollection(Collection<T> list, long totalCount) {
this.records = new Vector<T>();
this.records.addAll(list);
this.totalCount = totalCount;
}
}
The RESTful service calling this code looks like this:
package com.wdru.rest;
import javax.ws.rs.*;
import javax.ejb.*;
import com.wdru.facade.ClientFacadeRemote;
import com.wdru.facade.ClientStatusFacadeRemote;
import com.wdru.facade.CountedCollection;
import com.wdru.jpa.Client;
import com.wdru.jpa.ClientStatus;
@Path("/client")
@Produces("application/xml")
public class ClientRest {
@EJB
private ClientFacadeRemote cf;
@EJB
private ClientStatusFacadeRemote csf;
public ClientRest() {
}
@GET
public CountedCollection<Client> doGet(@QueryParam("dir") String sort_dir,
@QueryParam("sort") String sort_field,
@DefaultValue("0") @QueryParam("start") Integer start,
@DefaultValue("0") @QueryParam("limit") Integer limit) throws
Exception {
String sd = null;
if (sort_dir!=null) {
sd = sort_dir.toUpperCase();
}
return this.cf.readAll(start, limit, sd, sort_field);
}
.
.
.
All the entities in com.donotuse.jpa are annotated and serialize correctly.
With the XmlSeeAlso commented out, I get 'javax.xml.bind.JAXBException:
class com.donotuse.jpa.Client nor any of its super class is known to this
context.' gracing my log files. When I uncomment the @XmlSeeAlso, it
serializes just fine, but having to put a reference to every class that
might use this collection kind of defeats the purpose of using generics in
the first place.
So my questions is: what is the best way to go about doing this? Is there
some black magic I can use in the wrapper class that tells JAXB to use type
T instead of having to specify each type in XmlSeeAlso? Thanks for all
replies, advice, and flames in advance.
Cheers,
Pratap
--
View this message in context: http://www.nabble.com/Using-JAXB-with-generics-tp26054767p26054767.html
Sent from the java.net - jaxb users mailing list archive at Nabble.com.