2013-02-06 23 views
2

我很驚訝地看到JAXB解組在隨後的堆棧跟蹤過程中確實JAXB調用的getter:爲什麼解組

[#|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的意圖,它應該被標記不返回NULL,因爲getter也用@XmlElementRef註解(required = true)。所以基本上,@NotNull被放在那裏告訴客戶端,它不應該是null,因爲它在XML文件中的一個必需元素被解組,因此解析將失敗,因爲它的缺失或它將在那裏。有關@NotNull的更多信息可以在here找到。

在這種情況下,與getter相關聯的屬性是List<Bar>,該類未由類預初始化,因爲它預期解組過程將這樣做。

在任何情況下,我都看到如果在解組過程中解析失敗,JAXB會調用getter,並且會返回生成上述異常的@NotNull。

任何人都可以闡明這種行爲嗎?謝謝,

-Noah

回答

2

一個JAXB (JSR-222)執行默認情況下對待公共屬性映射。它調用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將使用從get方法返回的List實例。

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; 
    } 

} 
+0

有趣。我的JAXB註釋類看起來像你的第一個例子,其中'List'尚未初始化。但是,基於'@NotNull'觸發的IllegalStateException,它會顯示getter返回NULL和ArrayList的實例。也許是註釋與JAXB的問題? – NBW

+0

@NBW - 默認情況下,JAXB使用getter在解組過程中檢查屬性的值。在你的情況下,它將是'null'。然後,當JAXB看到該值爲空時,它會創建一個新的'ArrayList'實例。我已經更新了我的答案,以便讓這個更清楚。 –

+1

是的,現在很清楚。感謝您的見解!我有另一個Unmarshaller文件鎖定,我將很快發佈。 – NBW