2

JAXBのアンマーシャリング中に、次のスタックトレースを見て驚いた。

[#|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)

ゲッターにはorg.jetbrains.annotation.NotNullアノテーションが付けられており、ゲッターにも@XmlElementRef(required = true)アノテーションが付けられているため、NULLを返さないようにマークする必要があります。したがって、基本的に@NotNullは、XMLファイルの必須要素がマーシャリングされていないため、これがnullになることはないことをクライアントに通知するために配置されました。そのため、解析が失敗するか、存在しないために解析が失敗します。@NotNullの詳細については、こちらをご覧ください

この場合のゲッターに関連付けられているプロパティはList<Bar>、アンマーシャリングプロセスがそうすることが期待されるように、クラスによって何にも初期化されないaです。

いずれにせよ、アンマーシャリング中に解析が失敗した場合、JAXBがゲッターを呼び出し、これが@NotNullをトリップして、上記の例外を生成することがわかります。

誰かがこの行動に光を当てることができますか?ありがとう、

-ノア

4

1 に答える 1

2

JAXB(JSR-222)実装は、デフォルトでパブリックプロパティをマップされたものとして扱います。getをListプロパティに呼び出す理由は、値が事前に初期化されているかどうかを確認するためです。

シナリオ#1

JAXBはgetBars()、コレクションがすでに作成されているかどうかを確認するために呼び出します。これにより、が返されnullます。返されたのでnull、JAXBはインスタンスを作成します。そのインスタンスは。java.util.ArrayListを介して設定され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はListgetメソッドから返されたインスタンスを使用します。

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)、クラスまたはパッケージで指定できます(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;
    }

}
于 2013-02-06T00:45:33.837 に答える