0

I have some POJOs coming from a third party that are nested in a quite complex way and which I wish to use in an XML structure using JAXB. This alone would not be a problem. However, the provider of those POJOs managed to use an interface instead of a POJO in one single place deep down in the inheritance chain.

So I have a simplified POJO structure like

POJO class A
|-- POJO class B
    |-- field C is an interface of type D and not a POJO
    |-- other fields of POJO types
|-- POJO class B1 etc

I intend to use the POJO structure in my class M like this:

@XmlAccessorType(XmlAccessType.FIELD)
class M
{
    @XmlElementWrapper(name = "classAWrapper")
    @XmlElement(name = "classA", required = true)
    private List<ClassA> classAs = new ArrayList<>();
}

JAXB doesn't like it with an IllegalAnnotationException and "D is an interface, and JAXB can't handle interfaces."

Other solutions like JAXB Can't handle interfaces suggest adding @XmlJavaTypeAdapter(FooImpl.Adapter.class) to the interface. I, however, do not have access to the source code of interface D.

Is there a way in JAXB to tell the system in some general spot or in my class M what to do when it encounters interface D (specify a concrete class or something) so I can work around the issue?

Sebastian
  • 5,177
  • 4
  • 30
  • 47

1 Answers1

0

I found the solution after coming across the XmlJavaTypeAdapters annotation.

So if the interface D is used in package some.other.impl, you need to create that package in your source folder and add a package-info.java file.
Furthermore you need to add a class DAdapter extends XMLAdapter<SurrogateForD, D> implementation that converts to and from D as well as the SurrogateForD class.

Then, in the package-info.java add the following content:

@javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters({
    @javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter(value = DAdapter.class, type = D.class)
})
package some.other.impl;

And JAXB will use the SurrogateForD implementation when it encounters D anywhere it is used in package some.other.impl.
If D is used in other packages besides some.other.impl, add that other package to your source folder and add the package-info.java file as above (no need to copy the classes).

Sebastian
  • 5,177
  • 4
  • 30
  • 47