users@jersey.java.net

JAXB question regarding xsi: attributes

From: Laird Nelson <ljnelson_at_gmail.com>
Date: Thu, 15 Apr 2010 16:59:23 -0400

Hello. This is a JAX-RS and JAXB question, though it may not look
like it at first. Please bear with me.

I am using SmartGWT on the front end.

SmartGWT's REST Data Source is a feature that makes relatively simple
XML REST calls from the client to the server. The server is expected
to answer in a particular format.

The format of the server's response is absolutely brain dead simple,
and you can read all about it here:
http://www.smartclient.com/smartgwt/javadoc/com/smartgwt/client/data/RestDataSource.html

I'm also trying to make it so that my server-side objects don't have
to return data in a SmartGWT-specific format out of the box; I am
attempting through a MessageBodyWriter to wrap their results inside a
SmartGWT-friendly container. So in other words, in general, my
objects will return Collection<T>. I am trying to wrap that
Collection<T> so that it gets the SmartGWT-specific state wrapped
around it like so:

<response>
  <status>0</status>
  <startRow>0</startRow>
  <endRow>12</endRow>
  <totalRows>5047</totalRows>
  <data>
(Here are where my collection elements should go; if it's a
Collection<Gorp>, then I want "<gorp>" elements here)
  </data>
</response>

To do this, I have a MessageBodyWriter that accepts a Collection<T> as
spat back by my resource class. It creates a
RestDataSourceResponse<T> (the XML above, basically, in JAXB-Java
form), adds the Collection<T> to it (wraps the collection), and then
uses Providers to find a MessageBodyWriter capable of working with a
RestDataSourceResponse<T>, which will be the default JAXB serializer.

All is fine and good, except that I cannot for the life of me figure
out how to annotate the Collection<T> (how do I get "<gorp>" elements,
not "<record xsi:type='gorp'>" elements?).

What I mean is, if, inside RestDataSourceResponse<T>, I annotate it
like this, which seems to be the generally accepted solution for
collection XML binding:

  @XmlElementWrapper(name = "data")
  @XmlElement(name = "record")
  private Collection<T> data;

I *almost* get what I want. The @XmlElementWrapper gives me the
"data" element. That's neat.

But then the individual items so wrapped are named "record", and they
all have xsi:type=someRuntimeType. That is, if at runtime T is Gorp,
then I get <record xsi:type="gorp"> for each element of my collection.
 I really want them to be named T, as in whatever value T has at
runtime. I really want, in other words, that they be "<gorp>", in
this example. No attributes. No xsi:type.

Now, obviously an annotation can't do this purely on its own, because
an annotation sits on a class, and by definition you're not in runtime
mode at that point. But surely? somehow? with marshaling there must
be a way to hook into the JAXB marshaling process to achieve this?

(Others have had this problem as well and have butchered the living
snot out of it like so:
http://forums.smartclient.com/showthread.php?p=31182 Please tell me
there's a better way.)

Thanks,
Laird