views:

22

answers:

1

Hi,

I'm using JAXB to marshal a class that has an instance variable that's declared as class Foo. At runtime that instance variable is set to an instance of a subclass of Foo, let's say FooBar. There are basic JAXB annotations on both class Foo and FooBar.

The XML output shows that an instance of Foo is being marshaled instead of FooBar. Is there something specific I have to do in terms of annotations to tell JAXB how to properly marshal the runtime subclass in lieu of the declared superclass?

I tried an experiment in which I directly marshaled an instance variable foo of type Foo that was set to an instance of FooBar at runtime. It correctly marshaled an instance of FooBar.

This is clearly different from marshaling a class that contains an instance variable of type Foo because the marshal call is made on the containing class and JAXB just marshals that classes fields (I'm using the @XmlAccessorType(XmlAccessType.FIELD) annotation).

My expectation was that JAXB could properly inspect the runtime type of the instance variable but perhaps that's not the case. Does this situation call for using an implementation of XmlAdapter as described here?

http://stackoverflow.com/questions/619761/jaxb-inheritance-unmarshal-to-subclass-of-marshaled-class

Thanks,

Chris

+1  A: 

I'll use these classes as an example:

@XmlRootElement
class Foo { public Bar bar; }
class Bar {}
class Baz extends Bar {}
class Quux extends Bar {}

Well, there seem to be two possible solutions:

You can tell JAXB about all involved classes (including subclasses) at context creation time.

JAXBContext.newInstance(Foo.class, Bar.class, Baz.class, Quux.class);

You tell JAXB about the other classes via the @XmlSeeAlso annotation.

@XmlRootElement
@XmlSeeAlso({Baz.class, Quux.class})
class Foo { public Bar bar; }

If you marshal like this

Foo f = new Foo();
f.bar = new Baz();

m.marshal(f, System.err);

you receive

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<foo>
    <bar xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="baz"/>
</foo>

It's not beautiful but type information is preserved.

musiKk