I'm using JAXB to read and write XML. What I want is to use a base JAXB class for marshalling and an inherited JAXB class for unmarshalling. This is to allow a sender Java application to send XML to another receiver Java application. The sender and receiver will share a common JAXB library. I want the receiver to unmarshall the XML into a receiver specific JAXB class which extends the generic JAXB class.
Example:
This is the common JAXB class which is used by the sender.
@XmlRootElement(name="person") public class Person { public String name; public int age; }
This is the receiver specific JAXB class used when unmarshalling the XML. The receiver class has logic specific to the receiver application.
@XmlRootElement(name="person") public class ReceiverPerson extends Person { public doReceiverSpecificStuff() ... }
Marshalling works as expected. The problem is with unmarshalling, it still unmarshals to Person
despite the JAXBContext using the package name of the subclassed ReceiverPerson
.
JAXBContext jaxbContext = JAXBContext.newInstance(package name of ReceiverPerson);
What I want is to unmarshall to ReceiverPerson
. The only way I've been able to do this is to remove @XmlRootElement
from Person
. Unfortunately doing this prevents Person
from being marshaled. It's as if JAXB starts at the base class and works its way down until it finds the first @XmlRootElement
with the appropriate name. I've tried adding a createPerson()
method which returns ReceiverPerson
to ObjectFactory
but that doesn't help.
UNMARSHALLING. To unmarshal an xml string into a JAXB object, you will need to create an Unmarshaller from the JAXBContext, then call the unmarshal() method with a source/reader and the expected root object.
This exception indicates that an error has occurred while performing an unmarshal operation that prevents the JAXB Provider from completing the operation. The ValidationEventHandler can cause this exception to be thrown during the unmarshal operations.
In JAXB, marshalling involves parsing an XML content object tree and writing out an XML document that is an accurate representation of the original XML document, and is valid with respect the source schema. JAXB can marshal XML data to XML documents, SAX content handlers, and DOM nodes.
The following snippet is a method of a Junit 4 test with a green light:
@Test public void testUnmarshallFromParentToChild() throws JAXBException { Person person = new Person(); int age = 30; String name = "Foo"; person.name = name; person.age= age; // Marshalling JAXBContext context = JAXBContext.newInstance(person.getClass()); Marshaller marshaller = context.createMarshaller(); StringWriter writer = new StringWriter(); marshaller.marshal(person, writer); String outString = writer.toString(); assertTrue(outString.contains("</person")); // Unmarshalling context = JAXBContext.newInstance(Person.class, RecieverPerson.class); Unmarshaller unmarshaller = context.createUnmarshaller(); StringReader reader = new StringReader(outString); RecieverPerson reciever = (RecieverPerson)unmarshaller.unmarshal(reader); assertEquals(name, reciever.name); assertEquals(age, reciever.age); }
The important part is the use of the JAXBContext.newInstance(Class... classesToBeBound)
method for the unmarshalling context:
context = JAXBContext.newInstance(Person.class, RecieverPerson.class);
With this call, JAXB will compute a reference closure on the classes specified and will recognize RecieverPerson
. The test passes. And if you change the parameters order, you'll get a java.lang.ClassCastException
(so they must be passed in this order).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With