Я ожидаю, что следующий тест будет работать с Sun JAXB RI 2.2.1.1, но вместо этого он завершается с ошибкой NullPointerException при построении JAXBContext:
public class GenericFieldMarshallTest {
public static class CustomType {
}
public static class CustomTypeAdapter extends XmlAdapter<String, CustomType> {
@Override
public String marshal(CustomType v) throws Exception {
return "CustomType";
}
@Override
public CustomType unmarshal(String v) throws Exception {
return new CustomType();
}
}
@XmlJavaTypeAdapter(type = CustomType.class, value = CustomTypeAdapter.class)
public static class RootElement<ValueType> {
@XmlValue public ValueType value;
}
@XmlRootElement(name = "root")
public static class CustomRootElement extends RootElement<CustomType> {
public CustomRootElement() {
value = new CustomType();
}
}
@Test
public void test() throws Exception {
JAXBContext context = JAXBContext.newInstance(CustomRootElement.class,
CustomType.class, RootElement.class);
StringWriter w = new StringWriter();
context.createMarshaller().marshal(new CustomRootElement(), w);
assertThat(w.toString(), equalTo("<root>CustomType</root>"));
}
}
Исключение, которое я получаю:
java.lang.NullPointerException
at com.sun.xml.bind.v2.runtime.reflect.TransducedAccessor.get(TransducedAccessor.java:165)
at com.sun.xml.bind.v2.runtime.property.ValueProperty.<init>(ValueProperty.java:77)
at com.sun.xml.bind.v2.runtime.property.PropertyFactory.create(PropertyFactory.java:106)
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.<init>(ClassBeanInfoImpl.java:179)
at com.sun.xml.bind.v2.runtime.JAXBContextImpl.getOrCreate(JAXBContextImpl.java:515)
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.<init>(ClassBeanInfoImpl.java:166)
at com.sun.xml.bind.v2.runtime.JAXBContextImpl.getOrCreate(JAXBContextImpl.java:515)
at com.sun.xml.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:330)
at com.sun.xml.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1140)
at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:154)
at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:121)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:202)
at javax.xml.bind.ContextFinder.find(ContextFinder.java:363)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:574)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:522)
Причина, по-видимому, в том, что JAXB не знает, как маршалировать объявленный тип моего поля (который, я думаю, стирается в Object во время выполнения?), хотя во время выполнения я только когда-либо устанавливал для поля типы, о которых JAXB знает.
Как я могу маршалировать поле универсального типа?
(Замена @XmlValue на @XmlAttribute не устраняет исключение, равно как и изменение объявленного типа поля на Object, хотя, конечно, все работает нормально, если поле объявлено как String, за исключением того, что String нельзя назначить из CustomType. Размещение @XmlJavaTypeAdapter также не имеет значения; в моем реальном коде он устанавливается на уровне пакета в package-info.java.)