本文介绍了为什么JAXB在解组时会调用getter的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很惊讶在JAXB解组期间看到以下堆栈跟踪:

I was surprised to see the following stack trace during JAXB unmarshalling:

[#|2013-02-05T18:59:27.551-0500|SEVERE|glassfish3.1.2|ConfigurationService|_ThreadID=82;_ThreadName=Thread-2;|Exception processing C:\glassfish3\glassfish\domains\domain1\config\myConfig.xml : @NotNull method com/foo/services/config/Config.getBars must not return null
java.lang.IllegalStateException: @NotNull method com.foo.services.config.Config.getBars must not return null
    at com.foo.services.Config.getBars(Config.java:222)
    at com.foo.services.Config$JaxbAccessorM_getBars_setBars_java_util_List.get(MethodAccessor_Ref.java:56)
    at com.sun.xml.bind.v2.runtime.reflect.Lister$CollectionLister.startPacking(Lister.java:294)
    at com.sun.xml.bind.v2.runtime.reflect.Lister$CollectionLister.startPacking(Lister.java:269)
    at com.sun.xml.bind.v2.runtime.unmarshaller.Scope.start(Scope.java:142)
    at com.sun.xml.bind.v2.runtime.property.ArrayERProperty$ItemsLoader.startElement(ArrayERProperty.java:119)
    at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext._startElement(UnmarshallingContext.java:501)
    at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement(UnmarshallingContext.java:480)
    at com.sun.xml.bind.v2.runtime.unmarshaller.ValidatingUnmarshaller.startElement(ValidatingUnmarshaller.java:102)
    at com.sun.xml.bind.v2.runtime.unmarshaller.SAXConnector.startElement(SAXConnector.java:150)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:506)
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(XMLNSDocumentScannerImpl.java:376)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2715)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:607)
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:116)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:488)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:835)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:764)
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:123)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1210)
    at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:568)
    at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:218)
    at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:190)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:172)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:177)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:186)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:204)

getter用org.jetbrains.annotation.NotNull注释,意图是它应该标记为不返回NULL,因为getter也使用@XmlElementRef注释(required = true)。所以基本上@NotNull被放在那里告诉客户端,它应该永远不会为null,因为它在XML文件中的必需元素是未编组的,因此解析将失败,因为它丢失或将在那里。有关@NotNull的更多信息,请访问。

The getter is annotated with org.jetbrains.annotation.NotNull with the intent that it should be marked to not return NULL because the getter is also annotated with @XmlElementRef(required = true). So bascially the @NotNull was put there to tell clients hey this should never be null because its a required element in the XML file being unmarshalled and as such either the parsing will fail because its missing or its going to be there. More info on @NotNull can be found here.

在这种情况下,与getter关联的属性是 List< Bar> ,该类未由类初始化任何预期解密过程都会这样做的事情。

The property associated with the getter in this case is a List<Bar> which is not initialized by the class to anything as its expected that the unmarshalling process will do so.

在任何情况下,我都会看到如果在解组期间解析失败,JAXB会调用getter,这会导致产生上述异常的@NotNull跳闸。

In any case I am seeing that if the parsing fails during unmarshalling JAXB calls the getter and this trips the @NotNull which generates the above exception.

有人能说清楚这种行为吗?谢谢,

Can anyone shed light on this behavior? Thanks,

-Noah

推荐答案

A 实现将公共属性视为已映射。它调用你的 List 属性的原因是看你是否已经预先初始化了一个值。

A JAXB (JSR-222) implementation by default treats public properties as mapped. The reason it calls get on your List property is to see if you a value has been pre-initialized.

场景#1

JAXB将调用 getBars ()查看是否已经创建了一个集合,这将返回 null 。由于返回 null ,JAXB将创建 java.util.ArrayList 的实例,该实例将通过<$ c $设置c> setBars 。

JAXB will call getBars() to see if a collection has already been created, this will return null. Since null was returned JAXB will create an instance of java.util.ArrayList which will be set via setBars.

public class Foo {

    private List<Bar> bars;

    public List<Bar> getBars() {
        return bars;
    }

    public void setBars(List<Bar> bars) {
        this.bars = bars;
    }

}

场景#2

JAXB将调用 getBars()来查看是否已创建集合,这将返回 LinkList 的实例。由于未返回 null ,JAXB将使用get方法返回的 List 实例。

JAXB will call getBars() to see if a collection has already been created, this will return an instance of LinkList. Since null was not returned JAXB will use the instance of List returned from the get method.

public class Foo {

    private List<Bar> bars = new LinkedList<Bar>();

    public List<Bar> getBars() {
        return bars;
    }

    public void setBars(List<Bar> bars) {
        this.bars = bars;
    }

}

场景#3

如果您希望JAXB使用字段而不是属性,那么您可以指定 @XmlAccessorType(XmlAccessType.FIELD)(请参阅:)。

If you would rather that JAXB use the fields instead of the properties, then you can specify @XmlAccessorType(XmlAccessType.FIELD) on the class or package (see: http://blog.bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html).

@XmlAccessorType(XmlAccessType.FIELD)
public class Foo {

    private List<Bar> bars;

    public List<Bar> getBars() {
        return bars;
    }

    public void setBars(List<Bar> bars) {
        this.bars = bars;
    }

}

这篇关于为什么JAXB在解组时会调用getter的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-22 21:00
查看更多