Skip to main content

Runtime xml adapter selection?

3 replies [Last post]
michaljakob
Offline
Joined: 2005-05-18

Hi,

I have the following problem, whose distilled version could be described as follows. I have a simple class

<br />
@XmlRootElement<br />
public class PolymorphicList {<br />
    @XmlElement<br />
    public List list = new ArrayList();<br />
}<br />

which I'd like to marshal using JAXB 2.0. Now, the problem is that I want to be able to put instances of various classes into the list, including those that JAXB can't handle directly and for which an adapter is necessary. In my particular case, it is e.g. java.awt.Rectangle class.So I've written a simple adapter
<br />
public class RectangleAdapter extends XmlAdapter<br />

which marshals Rectangle into an array of 4 integers. If I use Rectangle type directly, such as in
<br />
public class RectangleHolder {<br />
	@XmlElement<br />
	@XmlJavaTypeAdapter(RectangleAdapter.class)<br />
	public Rectangle rectangle;<br />
}<br />

then I can easily tell JAXB to use the RectangleAdapter. However, how can I achieve the same effect in my PolymorphicList example? Is there a way to tell JAXB to choose an adapter based on the runtime class information about the marshalled object? The last paragraph in Koshuke's blog at

http://weblogs.java.net/blog/kohsuke/archive/2005/04/xmladapter_in_j.html

suggests that it's not possible and this would break declarativity. (In fact, I do not want to generate XML schema from my classes so I the declarativity is not important in my case.) Is that really the case? If so, what are possible alternative solutions? One might be writing a special

<br />
public class PolymorphicListWithRectanglesAdapter extends XmlAdapter,List><br />

adapter which would traverse the list and substitute Rectangle list items with the ones obtained by invoking RectangleAdapter.marshal(Rectangle) at them? Any other possibilities/tips?

Regards,
michal

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
kohsuke
Offline
Joined: 2003-06-09

I think your PolymorphicListWithRectanglesAdapter work-around would work.

I think some more thinking needs to be done around XmlAdapter for it to be really useful, but I don't know how to fix it.

michaljakob
Offline
Joined: 2005-05-18

In the particular case I described, PolymorphicListWithRectanglesAdapter should work (And I'll give it a try later).

However, I can imagine a situation when I want to marshal List

directly without wrapping it within the PolymorphicList class. Something like [code] List anonymousPolymorhphicList = new List(); anonymousPolymorhphicList.add(new Rectangle(...)); JAXBContext context = JAXBContext.newInstance(); Marshaller m = context.createMarshaller(); m.marshal(anonymousPolymorhpicList, ...); [/code] In this case, there is no chance to declaratively instruct JAXB to use adapters when marshalling instances of particular class in the list. There is no class to annotate as both Rectangle and List<...> are classes beyond my control. The example shown above might be more in the direction of Java-to-XML serialization rather than Java-XML binding so might not be the primary design goal for JAXB. Still very useful -- in my aaplication I take advantage of the XML serialization capability for circumventing AXIS limitations when dealing with more complex classes. I simply pass all arguments in web service invocations as Strings and rely on JAXB marshalling/unmarshalling capabilities at both ends. Thus, the ability to associate an adapter with JAXBContext would solve the problem in my case. I understand it breaks declarativity but if a better solution is not available why not giving the user a chance to decide what's his/her priority? That said, JAXB 2.0 is becoming a very useful piece of software and has already saved me a lot of time writing custom SAX parsers for web service complex parameter passing. Good work!
kohsuke
Offline
Joined: 2003-06-09

Right.

In the particular example you cited, first you can't just marshal a List object today as it is an interface.

Also, if you need to adapt objects at the root of your content tree, generally it's not too hard to invoke Adapter by yourself, so it's a lesser problem.

I do agree that adapters need some more thinking.