I am working with an XML structure that doesn't lend itself particularly well to being implemented in JAXB. The XML has a common outer element but the content varies by message type. There is no XSD for the XML but a reference document that (roughly) describes the schema.
I modeled this as
@XmlRootElement(name="apimessage")
class Message
{
...
@XmlAnyElement(lax=true)
public MessageBody getBody()
...
}
interface MessageBody
{
}
Then I have sub-classes of MessageBody like this:
@XmlRootElement(name="bodya")
class BodyA implements MessageBody
{
}
I hit the first problem while testing which was that when decoding a message the decoder knew nothing about the body so you end up with errors like
java.lang.ClassCastException: com.sun.org.apache.xerces.internal.dom.ElementNSImpl cannot be cast to com.xxx.MessageBody
I got around this by passing the sub-class types as parameters to the JAXBContext when I was initializing it.
Now this wasn't the end of my problems as these messages get passed over a web interface.. The error in that case was:
[com.sun.istack.SAXException2: class com.xxx.BodyA nor any of its super class is known to this context.
The solution is actually quite simple (although not very extensible) and that is you use the @XmlSeeAlso attribute to tell JAXB to register the sub-classes of MessageBody when the Message class is registered:
@XmlRootElement(name="apimessage")
@XmlSeeAlso({BodyA.class,BodyB.class})
class Message
{
...
And then it just works...