users@jersey.java.net

Re: Returning Heterogeneous Collections?

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Wed, 16 Apr 2008 10:19:05 +0200

Tom Davies wrote:
>
> On 16/04/2008, at 12:16 AM, Paul Sandoz wrote:
>> Hi Tom,
>>
>> I think it is due to JAXB marshalling rather than anything specific to
>> Jersey. Is an @XmlRootElement present on classes that extend
>> RepositoryData?
>>
>> See the JavaDoc of XmlRootElement [1].
>>
>
> Thanks Paul,
>
> I do have @XmlRoot Element on the subclasses.
>
> I think this blog post answers my question:
> http://weblogs.java.net/blog/kohsuke/archive/2006/04/why_doesnt_jaxb.html --
> I believe that it applies as much to marshalling to XML as unmarshalling
> to Java.
>
> My subclasses aren't statically reachable from the base class, so JAXB
> doesn't know about them.
>

Ah yes, thanks for setting me straight on the matter.


> One way to fix this would be to install my own subclass of
> XMLJAXBElementProvider which would create a JAXBContext which was
> initialised differently -- what's the best way to substitute my
> implementation?
>

It is possible to supply developer created JAXBContext implementations
based on the type that needs to be un/marshalled:

@Provider
public class JAXBContextResolver implements ContextResolver<JAXBContext> {
   public JAXBContext getContext(Class<?> objectType) {
     ...
   }
}

The runtime will detect if one or more ContextResolver<T> exist and will
aggregate them into one instance of ContextResolver<T>. Such a
ContextResolver<JAXBContext> is injected onto the message body
readers/writers used for JAXB processing.

So you could create a JAXBContext that knows about all the relevant
types. And then the JAXBContextResolver would return that JAXBContext
for those types. Unfortunately it is not possible to ask the JAXBContext
whether it knows about a type so it is necessary to do the look up
yourself. You can keep a Set<Class> or you could check the package name
of the type and see if it is compatible with the package names
associated with the JAXBContext, for example:

   private static final BASE_PACKAGE = "...";
   private final JAXBContext c;

   public JAXBContext getContext(Class<?> objectType) {
     String pn = objectType.getPackage().getName();
     return (pn.startsWith(BASE_PACKAGE) ? c : null;
   }

Paul.

-- 
| ? + ? = To question
----------------\
    Paul Sandoz
         x38109
+33-4-76188109