为什么JAXB在解组期间调用getter
在JAXB解组期间,我惊讶地看到以下堆栈跟踪:为什么JAXB在解组期间调用getter,jaxb,Jaxb,在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/
[#|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还使用@xmlementref(required=true)进行注释。因此,基本上,@NotNull放在那里是为了告诉客户端,这永远不应该是null,因为它是XML文件中被取消组分的必需元素,因此解析将失败,因为它丢失了,或者它将在那里。可以找到有关@NotNull的更多信息
在本例中,与getter关联的属性是一个列表
,该列表未被类初始化为解组过程预期的任何内容
在任何情况下,我都可以看到,如果解析在解组过程中失败,JAXB调用getter并触发@NotNull,它将生成上述异常
有人能解释这种行为吗?谢谢
-Noah默认情况下,实现将公共属性视为映射。它在列表
属性上调用get的原因是为了查看您的值是否已预初始化
情景#1
JAXB将调用getBars()
,查看是否已经创建了一个集合,这将返回null
。由于返回了null
,JAXB将创建java.util.ArrayList
的实例,该实例将通过setbar
进行设置
公共类Foo{
私人酒吧名单;
公共列表getbar(){
返回杆;
}
公共空心立杆(列表栏){
这个。巴=巴;
}
}
场景#2
JAXB将调用getbar()
以查看是否已经创建了一个集合,这将返回LinkList
的实例。由于未返回null
,JAXB将使用从get方法返回的List
实例
公共类Foo{
私有列表栏=新的LinkedList();
公共列表getbar(){
返回杆;
}
公共空心立杆(列表栏){
这个。巴=巴;
}
}
场景#3
如果希望JAXB使用字段而不是属性,那么可以在类或包上指定@xmlacessortype(xmlacesstype.FIELD)
(请参阅:)
@xmlacessortype(xmlacesstype.FIELD)
公开课Foo{
私人酒吧名单;
公共列表getbar(){
返回杆;
}
公共空心立杆(列表栏){
这个。巴=巴;
}
}
很有趣。我的JAXB注释类看起来像您的第一个尚未初始化“List”的示例。但是,根据“@NotNull”触发的IllegalStateException,getter似乎返回NULL vs.和ArrayList实例。也许注释与JAXB?@NBW之间存在问题-默认情况下,JAXB使用getter在解组过程中检查属性的值。在您的情况下,它将是null
。然后,当JAXB看到该值为null时,它将创建ArrayList
的一个新实例。我更新了我的答案,试图让这更清楚。是的,现在清楚了。谢谢你的见解!我还有另一个关于解组器文件锁定的问题,我将很快发布。@NBW-我已经为您的新问题添加了一个答案(请参阅:),这是否意味着在场景2中,永远不会调用setter?如果setter执行的操作不同于只设置this.bar=bar
那么如果它想在设置之前调用addbar()方法来执行某种验证呢?