CXF 解组日期不接受 NULL 值

CXF unmarshalling Date not accepting NULL value

我有一个包含 -

的 WSDL 文件
<xs:complexType name="PNV">
        <xs:sequence>
            <xs:element name="dataType" type="xsd:int" />
            <xs:element name="multiValued" type="xsd:boolean" />
            <xs:element name="booleanValue" type="xsd:boolean" />
            <xs:element name="dateValue" nillable="true" type="xsd:dateTime" />
            ..........

然后像这样转换成Java文件-

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "PNV", propOrder = {
    "dataType",
    "multiValued",
    "booleanValue",
    "dateValue",

})
public class PNV
    implements Serializable
{

    private final static long serialVersionUID = 1L;
    protected int dataType;
    protected boolean multiValued;
    protected boolean booleanValue;
    @XmlElement(required = true, type = String.class, nillable = true)
    @XmlJavaTypeAdapter(Adapter1 .class)
    @XmlSchemaType(name = "dateTime")
    protected Date dateValue;

}

绑定文件-

<jaxws:bindings  node="wsdl:definitions/wsdl:types/xs:schema[@targetNamespace='http://changeservice.xxservices.service.xx']">      
    <jxb:globalBindings xmlns:jxb="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema">        
    <jxb:javaType name="java.util.Date" xmlType="xs:dateTime" 
                  parseMethod="org.apache.cxf.xjc.runtime.DataTypeAdapter.parseDateTime"
                  printMethod="org.apache.cxf.xjc.runtime.DataTypeAdapter.printDateTime"/>    
        <jxb:serializable uid="1"/>     
    </jxb:globalBindings>  
</jaxws:bindings>

在我的 SOAPUI 测试用例中,我通过了 -

<dateValue nil="true"/>

但它给了我以下错误 -

Caused by: java.lang.IllegalArgumentException: 
    at com.sun.org.apache.xerces.internal.jaxp.datatype.XMLGregorianCalendarImpl$Parser.parseAndSetYear(XMLGregorianCalendarImpl.java:2891) ~[na:1.8.0_201]
    at com.sun.org.apache.xerces.internal.jaxp.datatype.XMLGregorianCalendarImpl$Parser.parse(XMLGregorianCalendarImpl.java:2777) ~[na:1.8.0_201]
    at com.sun.org.apache.xerces.internal.jaxp.datatype.XMLGregorianCalendarImpl.<init>(XMLGregorianCalendarImpl.java:436) ~[na:1.8.0_201]
    at com.sun.org.apache.xerces.internal.jaxp.datatype.DatatypeFactoryImpl.newXMLGregorianCalendar(DatatypeFactoryImpl.java:536) ~[na:1.8.0_201]
    at javax.xml.bind.DatatypeConverterImpl._parseDateTime(DatatypeConverterImpl.java:422) ~[na:1.8.0_201]
    at javax.xml.bind.DatatypeConverterImpl.parseDateTime(DatatypeConverterImpl.java:417) ~[na:1.8.0_201]
    at javax.xml.bind.DatatypeConverter.parseDateTime(DatatypeConverter.java:327) ~[na:1.8.0_201]
    at org.apache.cxf.xjc.runtime.DataTypeAdapter.parseDateTime(DataTypeAdapter.java:65) ~[cxf-xjc-runtime-3.3.1.jar:na]
    at org.w3._2001.xmlschema.Adapter1.unmarshal(Adapter1.java:13) ~[classes/:na]
    at org.w3._2001.xmlschema.Adapter1.unmarshal(Adapter1.java:1) ~[classes/:na]
    at com.sun.xml.bind.v2.runtime.reflect.AdaptedAccessor.set(AdaptedAccessor.java:55) ~[jaxb-runtime-2.3.3.jar:2.3.3]
    ... 107 common frames omitted

我检查了 Adapter1 class 中的日期属性,它显示为空白而不是 null,因此它引发了错误。我的问题是为什么即使我在我的 SOAPUI 测试用例中传递了 nil=true,它也没有采用 NULL 值。为什么它是空白的?我还尝试从我的输入请求中完全删除这个 dateValue 字段,它仍然给我相同的日期字段错误。

我也尝试使用 XMLGregorianCalendar 作为 dateValue 的一种类型,但是当我在 SOAPUI 中传递 nil=true 时,它​​给了我同样的错误信息。请帮助。

这个 link 帮助了我: https://blogs.oracle.com/rammenon/specifying-null-content-in-your-xml-document-using-nillable-and-xsi:nil

我在我的 SOAPUI 测试中添加了 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance 并添加了日期值

<dateValue xsi:nil="true"/>

如果您无法更改 wsdl 文件(以防由外部系统提供),您可以覆盖标准 org.apache.cxf.xjc.runtime.DataTypeAdapter

问题的根源不是 null,而是空字符串,作为 parseDateTime 方法的输入参数。

  1. 创建类似于“org.apache.cxf.xjc.runtime.DataTypeAdapter”的class,额外检查空字符串

     public class DateAdapter  {
    
     public static Date parseDateTime(String s) {
         if (s == null||s.isEmpty()) {
             return null;
         }
    
         return DatatypeConverter.parseDateTime(s).getTime();
     }
     public static String printDateTime(Date dt) {
         if (dt == null) {
             return null;
         }
         Calendar c = Calendar.getInstance();
         c.setTime(dt);
         return DatatypeConverter.printDateTime(c);
     }
    

    }

  2. 在绑定文件中指定新的class

    <jaxws:bindings  node="wsdl:definitions/wsdl:types/xs:schema[@targetNamespace='http://changeservice.xxservices.service.xx']">      
        <jxb:globalBindings xmlns:jxb="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema">        
        <jxb:javaType name="java.util.Date" xmlType="xs:dateTime" 
                      parseMethod="your_class_here.parseDateTime"
                      printMethod="your_class_here.printDateTime"/>    
            <jxb:serializable uid="1"/>     
        </jxb:globalBindings>  
    </jaxws:bindings>