我的問題是非常相似的How to prevent marshalling empty tags in JAXB when string is empty but not nullJAXB元帥空字符串空全球
不同的是,我無法添加註解的package-info.java從構造每個模式都產生所有的JAXB類型。 如果可能的話,我也不會更改JAXB提供程序。
我想要實現的是設置一個空字符串不會創建元素,但我需要爲來自多個模式的所有生成的JAXB類型設置此值。有沒有辦法將此應用於所有生成的JAXB類中的所有字符串字段?
更新 我已經設法獲得通過以下的改變模式中的所有字符串XML適配器生成:
在項目POM,我已將此添加到Maven的JAXB2-插件:
<bindingDirectory>src/main/resources</bindingDirectory>
<bindingIncludes>
<include>bindings.xjb</include>
</bindingIncludes>
這裏是我的bindings.xjb文件:
<jxb:bindings xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb" version="2.1">
<jxb:globalBindings>
<jxb:javaType name="java.lang.String" xmlType="xs:token"
parseMethod="com.project.Formatter.parseString"
printMethod="com.project.Formatter.printString"/>
</jxb:globalBindings>
</jxb:bindings>
而且格式方法:
public static String printString(final String value)
{
if (StringUtils.isBlank(value))
{
return null;
}
return value;
}
問題是,這會導致JAXB內深空指針異常。這裏是堆棧跟蹤:
Caused by: java.lang.NullPointerException
at com.sun.xml.bind.v2.runtime.output.SAXOutput.text(SAXOutput.java:158)
at com.sun.xml.bind.v2.runtime.XMLSerializer.leafElement(XMLSerializer.java:321)
at com.sun.xml.bind.v2.model.impl.RuntimeBuiltinLeafInfoImpl$1.writeLeafElement(RuntimeBuiltinLeafInfoImpl.java:210)
at com.sun.xml.bind.v2.model.impl.RuntimeBuiltinLeafInfoImpl$1.writeLeafElement(RuntimeBuiltinLeafInfoImpl.java:209)
at com.sun.xml.bind.v2.runtime.reflect.TransducedAccessor$CompositeTransducedAccessorImpl.writeLeafElement(TransducedAccessor.java:250)
at com.sun.xml.bind.v2.runtime.property.SingleElementLeafProperty.serializeBody(SingleElementLeafProperty.java:98)
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:322)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:681)
at com.sun.xml.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:150)
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:322)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:681)
at com.sun.xml.bind.v2.runtime.property.ArrayElementNodeProperty.serializeItem(ArrayElementNodeProperty.java:65)
at com.sun.xml.bind.v2.runtime.property.ArrayElementProperty.serializeListBody(ArrayElementProperty.java:168)
at com.sun.xml.bind.v2.runtime.property.ArrayERProperty.serializeBody(ArrayERProperty.java:152)
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:322)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:681)
at com.sun.xml.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:150)
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:322)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:681)
at com.sun.xml.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:150)
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:322)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:681)
at com.sun.xml.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:150)
at com.sun.xml.bind.v2.runtime.ElementBeanInfoImpl$1.serializeBody(ElementBeanInfoImpl.java:156)
at com.sun.xml.bind.v2.runtime.ElementBeanInfoImpl$1.serializeBody(ElementBeanInfoImpl.java:185)
at com.sun.xml.bind.v2.runtime.ElementBeanInfoImpl.serializeBody(ElementBeanInfoImpl.java:305)
at com.sun.xml.bind.v2.runtime.ElementBeanInfoImpl.serializeRoot(ElementBeanInfoImpl.java:312)
at com.sun.xml.bind.v2.runtime.ElementBeanInfoImpl.serializeRoot(ElementBeanInfoImpl.java:71)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:490)
at com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:328)
at com.sun.xml.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:257)
at javax.xml.bind.helpers.AbstractMarshallerImpl.marshal(AbstractMarshallerImpl.java:103)
這個問題的原因歸結爲這種方法:
com.sun.xml.bind.v2.runtime.reflect.TransducedAccessor.CompositeTransducedAccessorImpl.hasValue(BeanT)
上述方法將呈現元素,如果值不爲空任何適配器運行之前。
是否有任何方法可以重寫JAXB中使用的訪問器,以便在確定是否呈現該元素之前運行該適配器?有另一種方法來實現我想要的嗎?
看看JAXB綁定http://docs.oracle.com/cd/E17802_01/webservices/webservices/docs/1.5/tutorial/doc /JAXBUsing4.html – anazimok 2012-08-10 01:45:32
是的,我看了一下。不幸的是,模式文檔相當複雜,我需要將其應用於大約30種不同的模式。據我所知,必須爲每個綁定定義一個模式。有沒有辦法將綁定應用於所有生成的JAXB類? – 2012-08-10 02:33:41
您可以定義globalBinding請參閱我發佈的鏈接,我不記得哪個屬性確切,但其中一個屬性添加nillable到每個元素。也許這將有助於:http://stackoverflow.com/questions/4413281/how-do-i-prevent-jaxbelementstring-from-being-generated-in-a-cxf-web-service-c – anazimok 2012-08-10 03:40:36