Reputation: 155
I'm currently trying to use JaxB but i'm not being very successful with a relatively simple example. My example is the following:
public class A {
private String m_name;
}
public abstract class B_Base extends A {
}
public class B1 extends B_Base {
private String m_value1;
}
public class B2 extends B_Base {
private String m_value2;
}
All my attempts on (even marshalling) have failed. I have looked through Blaise Doughan's blog including articles such as http://blog.bdoughan.com/2010/11/jaxb-and-inheritance-using-xsitype.html but none of them seem to help on my example. It is certainly possible that i've misapplied his examples. I would seem to me that my example should be something that is easily supported in JaxB - after all, java is largely based on inheritance relationships!
I would be grateful for a fast response!
Upvotes: 2
Views: 2500
Reputation: 149047
You could do the following:
JAXBContext
on the leaf classes or you can use an @XmlSeeAlso
annotation on the parent class to pull in the sub classes.JAXBElement
.Demo
import javax.xml.bind.*;
import javax.xml.namespace.QName;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(B1.class, B2.class);
B1 b1 = new B1();
JAXBElement<A> jaxbElement = new JAXBElement<A>(new QName("root"), A.class, b1);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(jaxbElement, System.out);
}
}
Output
Below is the output from running the demo code:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="b1"/>
hi, probably a really stupid question, but just wondering, how would I adapt this if I have a class C that holds an ArrayList of A objects (or subclasses)?
C
Here is the C
class as described in your comment:
import java.util.*;
import javax.xml.bind.annotation.*;
@XmlRootElement
public class C {
private List<A> as = new ArrayList<A>();
@XmlElement(name="a")
public List<A> getAs() {
return as;
}
}
A
Here is how you can leverage the @XmlSeeAlso
annotation to bring in the subclasses.
@XmlSeeAlso({ B1.class, B2.class })
public class A {
private String m_name;
}
Below is some demo code to show everything works. Note now that we use @XmlSeeAlso
we use @XmlSeeAlso
we don't need to include the subclasses when bootstrapping JAXBContext
.
Demo
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(C.class);
C root = new C();
root.getAs().add(new B1());
root.getAs().add(new B2());
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(root, System.out);
}
}
Output
Below is the output from running the demo code.
<?xml version="1.0" encoding="UTF-8"?>
<c>
<a xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="b1"/>
<a xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="b2"/>
</c>
Upvotes: 2