On a generic typed Bean-Class, an Element of that Generic type may be marshaled and unmarshaled - this works.
But if the Generic Type gets bound to an abstract class, the unmarshaling Fails.
In the following example, I need a boundary for any type of Number, but JAXB tries to unmarshal this by instantiating to Number, which is abstract.
Ommitting the boundary or changing it to an instantiable type (like Object) solves the issue, but weakens the generics.
**JaxbTester.java**package de.panbytes.playground.jaxb;
import java.io.StringReader;
import java.io.StringWriter;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
public class JaxbTester {
/*
* AbstractContainer<T> -> works, but misses boundaries
* AbstractContainer<T extends Object> -> works, but boundaries are too large
* AbstractContainer<T extends Number> -> fails: "Exception in thread "main" javax.xml.bind.UnmarshalException: Unable to create an instance of java.lang.Number"
*/
static abstract class AbstractContainer<T /* extends Number */> {
@XmlElement
T someNumber;
}
@XmlRootElement
static class ContainerImpl<T extends Number> extends AbstractContainer<T> {
@SuppressWarnings("unused")
private ContainerImpl() {
// for JAXB
}
public ContainerImpl(final T someNumber) {
this.someNumber = someNumber;
}
}
/**
* @param args
*/
public static void main(final String[] args) throws Exception {
final AbstractContainer<Double> containerA = new ContainerImpl<>(42.5);
final JAXBContext context = JAXBContext.newInstance(ContainerImpl.class);
final Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
final StringWriter stringWriter = new StringWriter();
marshaller.marshal(containerA, stringWriter);
final String xmlString = stringWriter.toString();
System.out.println(xmlString);
final Unmarshaller unmarshaller = context.createUnmarshaller();
unmarshaller.setEventHandler(event -> {
System.err.println("!! " + event.getMessage() + " - " + event.getLocator() + "\n");
return true;
});
final Object unmarshal = unmarshaller.unmarshal(new StringReader(xmlString));
System.out.println("unmarshal: " + unmarshal.toString());
}
}
The marshaled XML is the following, in each case containing the correct xsi:type="xs:double".
On a generic typed Bean-Class, an Element of that Generic type may be marshaled and unmarshaled - this works. But if the Generic Type gets bound to an abstract class, the unmarshaling Fails.
In the following example, I need a boundary for any type of Number, but JAXB tries to unmarshal this by instantiating to Number, which is abstract. Ommitting the boundary or changing it to an instantiable type (like Object) solves the issue, but weakens the generics.
The marshaled XML is the following, in each case containing the correct xsi:type="xs:double".
Environment
Windows 10 / jdk1.8.0_91 / eclipse neon 4.6.0
Affected Versions
[2.2.8 (JDK 8)]