问题描述
我很惊讶在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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!