dev@jersey.java.net

Re: [Jersey] element name wrapper for List<Element> returned by Jersey method.

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Mon, 08 Feb 2010 10:13:21 +0100

Hi James,


On Feb 5, 2010, at 4:11 AM, James Russo wrote:

> Hello,
>
> This issue is described in http://stackoverflow.com/questions/
> 1545041 and http://stackoverflow.com/questions/2204729.
>
> Basically, when returning a list of JAXB objects, somehow it
> automagically places a plural wrapper element (I don't think it
> somehow references the JAXB objects) around the name, but it is in
> lower case.

Yes, it uses the class name of the item class. Our bad it should have
used the @XmlRootElement annotation, it present and retained the case.


> The responses on SO say that Paul had said it was a known issue and
> suggested introducing another class with XmlElementWrapper. However,
> I already have another class (People as a list of Person), but most
> of my methods returns List<Person>, so I'm having to update each
> method to create People object and copy all that data in (can't even
> set the list, since set method isn't generated by JAXB)..
>
> Any suggestions?
>

I will try and fix the issue this week.

Here are a number of possible solutions:

1) Use the @XmlRootElement defined on the item JAXB class, or same
rules to derive the name, and pluralize it (without lower casing it).

2) Annotate the resource method with @XmlRootElement (however that
might interfere if the resource class is also a JAXB
     class)

3) Annotate the JAXB class with a special Jersey annotation (the same
can apply for 2 as well).


I am leaning towards option 1), unfortunately we cannot make that the
default because we will break on the wire backwards compatibility. Do
you have any preference or further ideas on the matter?


In the interim there is a possible work around without having to
change your application code. Implement a resource filter that
modifies the entity and wraps it around an instance of Person.

https://jersey.dev.java.net/nonav/apidocs/latest/jersey/com/sun/jersey/api/container/filter/package-summary.html

Pseudo code at the end of the emal.

Hth,
Paul.

public class PersonWrapperResourceFilterFactory implements
ResourceFilterFactory {

     private class Filter implements ResourceFilter,
ContainerResponseFilter {

         // ResourceFilter

         public ContainerRequestFilter getRequestFilter() {
             return null;
         }

         public ContainerResponseFilter getResponseFilter() {
             return this;
         }

         // ContainerResponseFilter

         public ContainerResponse filter(ContainerRequest request,
ContainerResponse response) {
             Object e = response.getEntity();
             Person p = new Person((List<Person>)e);
             response.setEntity(p);
         }
     }

     public List<ResourceFilter> create(AbstractMethod am) {
         Type t = am.getMethod().getGenericReturnType()
         If (/type is equal to List<Person>/) {
             return Collections.<ResourceFilter>singletonList(new
Filter());
         }
         return null;
     }
}