When I marshall an instance of this class ...
@XmlRootElement
public static class TestSomething<T extends Serializable> {
T id;
public T getId() {
return id;
}
public void setId(T id) {
this.id = id;
}
}
... the following Exception is thrown ...
com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 2 counts of IllegalAnnotationExceptions
java.io.Serializable is an开发者_StackOverflow中文版 interface, and JAXB can't handle interfaces.
this problem is related to the following location:
at java.io.Serializable
at public java.io.Serializable TestSomething.getId()
at TestSomething
java.io.Serializable does not have a no-arg default constructor.
this problem is related to the following location:
at java.io.Serializable
at public java.io.Serializable TestSomething.getId()
at TestSomething
How can I avoid this (without changing the type parameter to something like <T>
)?
You need to use a combination of @XmlElement and @XmlSchemaType:
import java.io.Serializable;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSchemaType;
@XmlRootElement
public class TestSomething<T extends Serializable> {
T id;
@XmlElement(type=Object.class)
@XmlSchemaType(name="anySimpleType")
public T getId() {
return id;
}
public void setId(T id) {
this.id = id;
}
}
If you run the following:
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
public class Demo {
public static void main(String[] args) throws JAXBException {
JAXBContext jc = JAXBContext.newInstance(TestSomething.class);
TestSomething<Integer> foo = new TestSomething<Integer>();
foo.setId(4);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(foo, System.out);
}
}
You will get:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<testSomething>
<id xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:int">4</id>
</testSomething>
Here is a guide how to use interfaces with JAXB.
JAXB needs concrete classes, because it has to instantiate them when marshalling from XML. And if T
is no concrete class, it can't be instantiated.
Adding @XmlAnyElement
to the 'id' field (along with @XmlAccessorType(XmlAccessType.FIELD)
annotation at class level) or adding the same for getter will resolve this. (But it makes the xml element's type any
.)
精彩评论