5

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.

limouren
  • 116
  • 4

0 Answers0