users@jersey.java.net

Java generics with Jersey

From: Damiano ALBANI <damiano.albani_at_univ-nantes.fr>
Date: Thu, 07 Oct 2010 11:15:34 +0200

Hello,

I'd like to use Java generics in my JAX-RS project with Jersey, due to
the way my ExtJS client requires XHR payloads to be formatted.
Basically, that would consist of a very simple wrapper like:

  public class ExtJsWrapper<T> {
    public T rows;
  }

Jersey is able to correctly marshall objects of such type, e.g.:

  @GET
  public ExtJsWrapper<Campagne> getCampagne() {
    Campagne campagne = ...
    return new ExtJsListWrapper<Campagne>(campagne);
  }

Works fine, JSON/XML is generated when I fetch the resource by GET.
Now, I found unmarshalling is a bit trickier, when I need to support
generics as input parameters:

  @PUT
  @Path("{id}")
  public ExtJsWrapper<Campagne>
    updateCampagne(@PathParam("id") int idCampagne,
                   ExtJsWrapper<Campagne> wrapper) {
    ...
  }

With JSON, I found that I needed to specified a "type" property,
otherwise Jersey would fail.

  curl -X PUT -H "Content-Type: application/json"
       -d '{ "rows": { "type":"campagne", "id":1, "code":"10-1" } }'
        http://localhost:8080/api/campagnes/2

By the way, what's "funny" is that Jersey is picky about where the
"type" property lies in the JSON !?
For instance, this fails:

  curl -X PUT -H "Content-Type: application/json"
       -d '{ "rows": { "id":1, "code":"10-1", "type":"campagne" } }'
        http://localhost:8080/api/campagnes/2

So, is there a way to avoid having to specify this type property in my
JSON (or XML) data?

After a bit of Googling, I've seen references to these 2 classes that
might help:
  javax.ws.rs.core.GenericEntity<T>
  com.sun.jersey.api.client.GenericType<T>

But how shall I use them in my code?

Finally, I've got another blocking issue, this time with generics in the
Jersey Client API.
If I want to call the PUT method as shown above, how can I do it?

I've tried things like:

  Campagne campagne = ...

  ressource.accept(MediaType.APPLICATION_JSON_TYPE)
           .type(MediaType.APPLICATION_JSON_TYPE)
           .put(new GenericType<ExtJsWrapper<Campagne>>() {}, campagne);

Also tried playing with all sorts of combinations with
GenericEntity/GenericType... without success :-(
I keep on getting this exception:

  com.sun.jersey.api.client.ClientHandlerException:
javax.ws.rs.WebApplicationException: javax.xml.bind.MarshalException
   - with linked exception:
  [javax.xml.bind.JAXBException: class
fr.univNantes.spin.entities.Campagne nor any of its super class is known
to this context.]

Sorry for this long message but I couldn't find any solution even after
many attempts...

Thanks for your help,

-- 
Damiano ALBANI