我希望下面的测试与Sun的JAXB RI 2.2.1.1工作,而是它失败,一个NullPointerException在构建的JAXBContext:JAXB编组场,它的类型是一个泛型类型参数
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不知道如何封送我的字段的声明类型(?我认为这是消除在运行时对象),即使在运行时我只将该字段设置为JAXB知道的类型。
如何编组一个类型为通用的字段?
(用@XmlAttribute替换@XmlValue并不能修复异常,也不会修改字段的声明类型为Object,当然如果该字段被声明为String,那么一切正常,但String不能从CustomType。@XmlJavaTypeAdapter的放置也没有区别;在我的实际代码中,它在package-info.java中设置在包级别上。)
你对XmlAdapter类型的顺序是正确的,我打算让它们成为另一种方式。当我为我的问题编写假示例时,这是一个转录错误。我已经解决了这个问题。 但是,其余的建议都不会导致我为其编写代码。 @XmlJavaTypeAdapter注释的位置是任意的;在我的实际代码中,它位于package-info.class的包级别。 我试过在JAXB无法找到它们本身的情况下,将涉及的其他类添加到JAXBContext.newInstance()调用中,但这对问题也没有任何影响。 – DanC 2010-06-29 12:17:46
如果你在我的问题中有一个测试版本,你可以把它放在一个pastebin中并链接到它,所以我们可以看到你为了使它工作而改变了什么? – DanC 2010-06-29 12:18:37
我编辑了帖子。不需要像pastebin那样引入外部依赖关系。我希望这适用于您,因为我使用JAXB,因为它随JDK一起分发。 – musiKk 2010-06-30 07:55:26