【问题标题】:Unmarshal NullPointerException (with JAXB reference implementation)Unmarshal NullPointerException(带有 JAXB 参考实现)
【发布时间】:2014-04-09 04:20:53
【问题描述】:

我正在尝试解组 xml 文件,但从 JAXB 库的深处得到了非常奇怪的 NPE。请问您能帮我解决这个问题吗?

这是异常堆栈跟踪的顶部:

java.lang.NullPointerException
at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:258)
at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.handleGenericException(Loader.java:245)
at com.sun.xml.bind.v2.runtime.unmarshaller.Scope.add(Scope.java:123)
at com.sun.xml.bind.v2.runtime.property.ArrayERProperty$ReceiverImpl.receive(ArrayERProperty.java:213)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.endElement(UnmarshallingContext.java:538)

这里是xml类代码:

public class Base {
    public Base() {
    }
}

public class A  extends Base {
    public A() {
    }
}

public class B extends Base{
    public B() {
    }
}


@XmlRootElement(name = "test")
@XmlAccessorType
public class TestXml {
    @XmlElementWrapper(name = "list")
    @XmlAnyElement
    @XmlJavaTypeAdapter(Adapter.class)
    public List<Base> list = new ArrayList<>();
}

这里是适配器的unmarshal()方法,取自here,稍作修改。

@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public T unmarshal(Element element) throws Exception {
    if (null == element) {
        return null;
    }

    // 1. Determine the values type from the type attribute.
    Class<?> clazz = classLoader.loadClass(element.getAttribute("class"));

    // 2. Unmarshal the element based on the value's type.
    DOMSource source = new DOMSource(element);
    Unmarshaller unmarshaller = getJAXBContext(clazz).createUnmarshaller();
    JAXBElement jaxbElement = unmarshaller.unmarshal(source, clazz);

    return (T) jaxbElement.getValue();      
}

这里是测试代码:

JAXBContext jaxbContext = JAXBContext.newInstance(TestXml.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();       

TestXml auth = (TestXml) unmarshaller.unmarshal(new File("testData/test.xml"));

最后,这是我尝试解组的 xml 文件:

<test>
    <list>
        <item class="my.package.A" />
        <item class="my.package.B" />
    </list>
</test>

在调试时我发现适配器运行良好,即 unmarshall() 方法总是返回正确类的实例,但之后发生了一些不好的事情。

接下来我发现的是适配器的代码

JAXBElement jaxbElement = unmarshaller.unmarshal(source, clazz);

导致 NPE。当我删除这行代码并将 unmarshall() 的 return 语句替换为

return new A(); //for example

没有发生 NPE。

【问题讨论】:

    标签: java xml nullpointerexception jaxb


    【解决方案1】:

    尝试更改此行,

    // 1. Determine the values type from the type attribute.
        Class<?> clazz = classLoader.loadClass(element.getAttribute("class"));
    

    到,

    // 1. Determine the values type from the type attribute.
        Class<?> clazz = ClassLoader.loadClass(element.getAttribute("class"));
    

    你的 clazz 变量的原因是空的。

    【讨论】:

    • Aditya,ClassLoader 类没有静态方法 loadClass :-( 我使用 Java 7.
    • 检查你是否使用了java.lang.ClassLoader,因为java7中的ClassLoader有loadClass方法。检查此链接,docs.oracle.com/javase/7/docs/api/java/lang/…
    • 是的,有,但是这个方法不是静态的。
    • 您可以使用 Class.forName 或参考此答案以使用 loadClass 方法加载您的类,stackoverflow.com/a/18679222/2968614
    • classLoader 找到类,所以 clazz 变量不为空。是的,我通过这种方式得到这个类加载器:classLoader = Thread.currentThread().getContextClassLoader();
    【解决方案2】:

    在另一个解组过程中尝试处理一个解组过程时,我有完全相同的堆栈跟踪。

    基本上,在适配器的“解组”方法中,我通过剥离其值并仅保留其属性来构建一个假“标签”。然后,为了正确提取属性,我使用了 jaxb 解组。

    错误在 jaxb 中很深,我真的没有在我的代码中看到任何错误。我通过从 2.2.6 迁移到 2.2.11 的最新和最好的 jaxb-core 库解决了我的问题。

    【讨论】:

      【解决方案3】:

      这是 JDK 1.7 中包含的 JAXB (2.2.4-2) 版本中的一个错误。

      对我来说,在类路径中包含最新版本的 JAXB (2.2.11) 解决了这个问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-12-11
        • 1970-01-01
        • 2014-04-07
        • 1970-01-01
        • 1970-01-01
        • 2012-07-09
        相关资源
        最近更新 更多