Apache CXF 为 xsd:choice 中未选择的选项生成 nil 元素,然后模式验证失败

Apache CXF generates nil elements for options not chosen in xsd:choice, then fails schema validation

对于 CXF 3.1.3,我的网络服务客户端提交了无效的 jaxb soap 请求。它在不应该的时候创建了两个 nil 元素。当我手动删除 soapui 测试套件中的两个 nil 元素时,请求正文会正确验证 xsd 模式。

架构部分...

<xsd:complexType name="RequestContentType">
    <xsd:complexContent>
        <xsd:extension base="structures:ObjectType">
            <xsd:choice>
                <xsd:element ref="ilcs:MessageID" />
                <xsd:element ref="nc:CaseDocketID" />
                <xsd:element ref="nc:DateRange" />
            </xsd:choice>
        </xsd:extension>
    </xsd:complexContent>
</xsd:complexType>

生成的无效请求部分...

        <ns4:RequestContent>
            <ns4:MessageID xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
            <ns2:CaseDocketID xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
            <ns2:DateRange>
                <ns2:StartDate>
                    <ns2:Date>2015-11-13-07:00</ns2:Date>
                </ns2:StartDate>
                <ns2:EndDate>
                    <ns2:Date>2015-12-22-07:00</ns2:Date>
                </ns2:EndDate>
            </ns2:DateRange>
        </ns4:RequestContent>

在构建请求对象的 java7 代码中,日期范围是唯一在 RequestContentType 对象中设置的内容。其他两个选择选项 messageId 和 caseDocketId 未设置。在运行时,messageId 和 caseDocketId 为空。

    DateRangeType dr = new DateRangeType();
    dr.setStartDate(NiemConverter.toDateType(oldest.getSubmittedToHfs()));
    dr.setEndDate(NiemConverter.toDateType(newest.getSubmittedToHfs()));
    RequestContentType rct = new RequestContentType();
    rct.setDateRange(dr);

    StatusRequestType req = new StatusRequestType();
    req.setFIPSCode(proxy(fipsCode));
    req.setRequestContent(rct);

谁能提出为什么 CXF 为 null java 引用构建 nil 元素?或者如何停止?

下面的文件是由 maven cxf-codegen-plugin 在 "wsdl2java" 执行目标中生成的。

package g.i.h.d.c.extension._1;

import java.io.Serializable;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
import gov.niem.release.niem.niem_core._3.DateRangeType;
import gov.niem.release.niem.proxy.xsd._3.String;
import gov.niem.release.niem.structures._3.ObjectType;


/**
 * <p>Java class for RequestContentType complex type.
 * 
 * <p>The following schema fragment specifies the expected content contained within this class.
 * 
 * <pre>
 * &lt;complexType name="RequestContentType"&gt;
 *   &lt;complexContent&gt;
 *     &lt;extension base="{http://release.niem.gov/niem/structures/3.0/}ObjectType"&gt;
 *       &lt;choice&gt;
 *         &lt;element ref="{http://dcss.hfs.illinois.gov/csidews/extension/1.0}MessageID" minOccurs="0"/&gt;
 *         &lt;element ref="{http://release.niem.gov/niem/niem-core/3.0/}CaseDocketID" minOccurs="0"/&gt;
 *         &lt;element ref="{http://release.niem.gov/niem/niem-core/3.0/}DateRange" minOccurs="0"/&gt;
 *       &lt;/choice&gt;
 *       &lt;anyAttribute processContents='lax' namespace='urn:us:gov:ic:ntk urn:us:gov:ic:ism'/&gt;
 *     &lt;/extension&gt;
 *   &lt;/complexContent&gt;
 * &lt;/complexType&gt;
 * </pre>
 * 
 * 
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "RequestContentType", propOrder = {
    "messageID",
    "caseDocketID",
    "dateRange"
})
public class RequestContentType
    extends ObjectType
    implements Serializable
{

    @XmlElement(name = "MessageID", nillable = true)
    protected String messageID;
    @XmlElement(name = "CaseDocketID", namespace = "http://release.niem.gov/niem/niem-core/3.0/", nillable = true)
    protected String caseDocketID;
    @XmlElement(name = "DateRange", namespace = "http://release.niem.gov/niem/niem-core/3.0/", nillable = true)
    protected DateRangeType dateRange;

    /**
     * Gets the value of the messageID property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getMessageID() {
        return messageID;
    }

    /**
     * Sets the value of the messageID property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setMessageID(String value) {
        this.messageID = value;
    }

    /**
     * Gets the value of the caseDocketID property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getCaseDocketID() {
        return caseDocketID;
    }

    /**
     * Sets the value of the caseDocketID property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setCaseDocketID(String value) {
        this.caseDocketID = value;
    }

    /**
     * Gets the value of the dateRange property.
     * 
     * @return
     *     possible object is
     *     {@link DateRangeType }
     *     
     */
    public DateRangeType getDateRange() {
        return dateRange;
    }

    /**
     * Sets the value of the dateRange property.
     * 
     * @param value
     *     allowed object is
     *     {@link DateRangeType }
     *     
     */
    public void setDateRange(DateRangeType value) {
        this.dateRange = value;
    }

}

cxf-codegen-plugin 生成的代码有 nillable="true",因为元素 CaseDocketID 的定义是 nillable="true",参见 XSD:

<xs:element name="CaseDocketID" type="niem-xs:string" nillable="true">
    <xs:annotation>
        <xs:documentation>An identifier used to reference a case docket.</xs:documentation>
    </xs:annotation>
</xs:element>

无法更改元素引用中的 nillable,请参阅 W3C XML Schema Definition Language (XSD):

2 If the item's parent is not <schema>, then all of the following are true:

2.1 One of ref or name is present, but not both.

2.2 If ref is present, then no unqualified attributes are present other than minOccurs, maxOccurs, and id, and no children in the Schema namespace (xs) other than <annotation>.

Apache CXF 网络服务请求有效。

一位同事为我解决了这个问题。显然,他之前已经 运行 讨论过这个问题几次。他构建了一个去除 nil 元素的 xsl 文件。然后我将该文件作为资源 bean 添加到我的 jaxws 客户端配置中,作为出站 xslt 功能。 xsl 文件通过剥离 nil 元素来转换出站 xml。 saxon-8-dom.jar 是必需的依赖项。现在我的出站请求正确验证并被远程服务接受。