users@jersey.java.net

Re: [Jersey] Best practices for client specific serialization customization

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Fri, 17 Oct 2008 17:54:31 +0200

On Oct 17, 2008, at 2:52 PM, Kytömäki, Janne wrote:

> Hi,
>
> Thank you, Paul and others, for your input, escpecially for the StaX
> wrapper hint.
>
> Starting with the simpler solution, I managed to build an
> XMLStreamWriter wrapper to do the actual filtering of elements. It
> keeps track of the object path and forwards matching elmenents to
> the underlying XMLStreamWriter. What would be the preferred way of
> getting the wrapper to hook into the marshalling process?

You can avoid wrapping JAXB context by providing an implementation of :

   ContextResolver<Marshaller>

There is a JAXB helper class that provides a partial implementation of
Marshaller:

   http://java.sun.com/javase/6/docs/api/javax/xml/bind/helpers/AbstractMarshallerImpl.html


> XMLStreamWriter is created by Marshaller, which is created by
> JAXBContext, and I ended up building wrappers for both of these
> classes too. A bit ugly, and this also creates a problem with JSON
> marshalling since JSONRootElementProvider's writeTo method (v1.0
> line 113) omits JSON properties if the provided Marshaller isn't
> instanceof JSONMarshaller, which the wrapper isn't. Any ideas?
>

Can you log an issue for JSON? When required the JSON support needs to
work correctly from the StAX abstraction, in addition to supporting an
optimal path when StAX is not required.


> Using hypermedia for the omitted elements is also a good idea that
> might come handy once the application gets more complex.
>
> As for the client's interface to this customization process, I ended
> up with request parameter "includes" which has a comma separated
> list of Ant style directory patterns. If no includes are defined or
> the service in question doesn't support the feature, the whole
> object tree is returned. Includes pattern "*" only returns the first
> level of elements, "*,*/*,*/*/*" returns first three levels, "**/id"
> returns all elements named 'id' (and of course the path of elements
> leading to that element).
>
> As I couldn't figure out how to pass request scoped parameters to
> the JAXBContext wrapper, I'm passing the includes parameter to the
> JAXB processing by making the root element object being serialized
> implement a custom interface ({ public String getIncludes(); }),
> which is detected in the Marshaller wrapper.
>

In the ContextResolver implementation you can inject UriInfo:

   public LayeringResolver implements ContextResolver<Marshaller> {
     @Context UriInfo ui;

   }

from UriInfo you can get access to the map of query parameters.


>
> Oh, and congrats for the 1.0 and thanks for the good work and the
> great project!
>

Thanks!
Paul.


> Regards,
> Janne
>
> Date: Thu, 09 Oct 2008 17:05:46 +0200
> From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
> Content-type: text/plain; delsp=yes; format=flowed; charset=ISO-8859-1
> Subject: [Jersey] Best practices for client specific serialization
> customization
> Hi Janne,
>
> You raise a very interesting point. Some type of query parameter to
> declare the nesting level could do it. Or perhaps default nesting
> levels s could be declared depending on the User-Agent.
>
> IMHO i think for this type of thing hypermedia is really important:
>
> <!-- a nesting of 3 -->
> <employees>
> <employee href="..."/>
> <id>123</id>
> <firstName>John</firstName>
> <lastName>Doe</lastName>
> <address href="..."/>
> <department href="..."/>
> </employee>
> <employee href="..."/>
> <id>234</id>
> ..
> </employee>
>
> This way limited clients could make more smaller requests. While less
> limited clients could make fewer larger requests but it all works
> consistently via the hypermedia.
>
> Currently this is harder to do that it should be. We need better
> integration support with JAXB for working with hypermedia and
> connecting it to resource classes.
>
> A simpler non-hypermedia type solution may be possible to limit the
> nesting if JAXB marshaling can be customized. For example a StAX
> wrapper could keep track of the hierarchy and not omit XML elements
> below a certain nesting level.
>
> Paul.
>
> On Oct 9, 2008, at 1:34 PM, Kytömäki, Janne wrote:
>
> > Hi,
> >
> > Since Victor got an answer for best practices for JAX-RS paging,
> > I'll give it a shot too with different problem. :-)
> >
> > Objects serialized and returned by JAX-RS services may be complex
> > and have lots of nested objects, thus an XML serialized list of just
> > a few objects can weight tens or hundreds of kb's. Some clients,
> > like a web AJAX application with large screen estate, may find all
> > of this data useful and have no problem with even large file
> > transfers, whereas other clients, such as a mobile application,
> > might prefer getting only a subset of data per object that it can
> > quickly (and cheaply) download and fit on its limited screen and
> > then get the details for a particular object when needed via a
> > subsequent JAX-RS request. It feels a bit cludgy to implement
> > separate JAX-RS services for example for the AJAX and the mobile
> > application, one that would return the full object trees and one
> > that would only return limited versions of the objects. Does anybody
> > have any ideas how one should make the object serialization
> > customizable by the client with JAX-RS while using the same service
> > and same source objects? Perhaps the client should define required
> > object properties in the request and these should be passed to the
> > JAXB binding process somehow in the service?
> >
> > Example:
> >
> > Let's say we have a JAX-RS service /employees/ that returns a list
> > of all employees for a company. An example of returned document in
> > XML format:
> >
> > <employees>
> > <employee>
> > <id>123</id>
> > <firstName>John</firstName>
> > <lastName>Doe</lastName>
> > <address>
> > <street>Abc 123</street>
> > <city>New York</city>
> > <zip>12345</<zip>
> > </address>
> > <department>
> > <id>123</id>
> > <name>Marketing</name>
> > <parentDepartment>
> > <id>234</id>
> > <name>Corporate Services</name>
> > <parentDepartment>
> > <id>345</id>
> > <name>Acme Ltd.</name>
> > </parentDepartment>
> > </parentDepartment>
> > <department>
> > </employee>
> > <employee>
> > <id>234</id>
> > ..
> > </employee>
> > ..
> > ..
> > ..
> > <employees>
> >
> > The example AJAX application client prefers this full object
> > serialization, but the limited mobile client would prefer only
> > getting the employee id's and names to populate a list, and when
> > required (i.e. user selects an employee on the list), it would then
> > call /employee/{id} to get the details for a particular employee:
> >
> > <employees>
> > <employee>
> > <id>123</id>
> > <firstName>John</firstName>
> > <lastName>Doe</lastName>
> > </employee>
> > <employee>
> > <id>234</id>
> > ..
> > </employee>
> > ..
> > ..
> > ..
> > <employees>
> >
> > Thanks,
> > Janne
> >
> >
>
>
>
>
>