I am currently designing a generic message exchange format for a client-server communication. Within the message there is a field that will be overrided by each specific webservice. Simplified example follows:
class Message {
public BasicInfo basicInfo;
}
BasicInfo
is the base class. All derived classes will not have public no-args constructor. So I wrote XmlAdapter
for them.
@XmlJavaTypeAdapter(...)
class SpecificInfoA extends BasicInfo {
// Detail omitted
}
Then I updated the class Message
, hoping that jaxb is able to determine the class at runtime and use corresponding adapter to transform the object...
@XmlRootElement
@XmlSeeAlso({SpecificInfoA.class})
class Message {
@XmlAnyElement
public BasicInfo basicInfo;
}
But when I create the JAXBContext
:
JAXBContext context = JAXBContext.newInstance(Message.class);
An exception is thrown:
com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
playground.SpecificInfoA does not have a no-arg default constructor.
this problem is related to the following location:
at playground.SpecificInfoA
at @javax.xml.bind.annotation.XmlSeeAlso(value=[class playground.SpecificInfoA])
at com.sun.xml.bind.v2.runtime.IllegalAnnotationsException$Builder.check(IllegalAnnotationsException.java:106)
at com.sun.xml.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:466)
at com.sun.xml.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:298)
at com.sun.xml.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:141)
at com.sun.xml.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1157)
at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:145)
Since SpecificInfoA
has a XmlAdapter
, I expected jaxb to be able to add it to its context, but from the exception above, is it simply impossible to do so or am I doing it wrong?
I know I can write a general XmlAdapter
for BasicInfo
that converts instances to a general bind type when marshalling and create specific instances back when unmarshalling. However it would tightly couple all derived classes into one adapter, which is undesired.