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>
* <complexType name="RequestContentType">
* <complexContent>
* <extension base="{http://release.niem.gov/niem/structures/3.0/}ObjectType">
* <choice>
* <element ref="{http://dcss.hfs.illinois.gov/csidews/extension/1.0}MessageID" minOccurs="0"/>
* <element ref="{http://release.niem.gov/niem/niem-core/3.0/}CaseDocketID" minOccurs="0"/>
* <element ref="{http://release.niem.gov/niem/niem-core/3.0/}DateRange" minOccurs="0"/>
* </choice>
* <anyAttribute processContents='lax' namespace='urn:us:gov:ic:ntk urn:us:gov:ic:ism'/>
* </extension>
* </complexContent>
* </complexType>
* </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 是必需的依赖项。现在我的出站请求正确验证并被远程服务接受。
对于 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>
* <complexType name="RequestContentType">
* <complexContent>
* <extension base="{http://release.niem.gov/niem/structures/3.0/}ObjectType">
* <choice>
* <element ref="{http://dcss.hfs.illinois.gov/csidews/extension/1.0}MessageID" minOccurs="0"/>
* <element ref="{http://release.niem.gov/niem/niem-core/3.0/}CaseDocketID" minOccurs="0"/>
* <element ref="{http://release.niem.gov/niem/niem-core/3.0/}DateRange" minOccurs="0"/>
* </choice>
* <anyAttribute processContents='lax' namespace='urn:us:gov:ic:ntk urn:us:gov:ic:ism'/>
* </extension>
* </complexContent>
* </complexType>
* </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
orname
is present, but not both.2.2 If
ref
is present, then no unqualified attributes are present other thanminOccurs
,maxOccurs
, andid
, 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 是必需的依赖项。现在我的出站请求正确验证并被远程服务接受。