SOAP、JAXB 编组行为
SOAP, JAXB marshalling behavior
我有一个 WSDL 规范,使用 wsimport
生成客户端代码。 (就像我之前做过很多次一样)。
现在,xsd中的一种类型:
<xs:complexType name="Credential">
<xs:sequence>
<xs:element minOccurs="0" name="UID" nillable="true" type="xs:string"/>
<xs:element minOccurs="0" name="UIDBranch" nillable="true" type="xs:string"/>
<xs:element minOccurs="0" name="PWD" nillable="true" type="xs:string"/>
<xs:element minOccurs="0" name="Signature" nillable="true" type="xs:string"/>
</xs:sequence>
</xs:complexType>
和对应的java绑定:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Credential", namespace = "http://schemas.datacontract.org/2004/07/...", propOrder = {
"uid",
"uidBranch",
"pwd",
"signature"
})
public class Credential {
@XmlElementRef(name = "UID", namespace = "http://schemas.datacontract.org/2004/07/...", type = JAXBElement.class, required = false)
protected JAXBElement<String> uid;
@XmlElementRef(name = "UIDBranch", namespace = "http://schemas.datacontract.org/2004/07/...", type = JAXBElement.class, required = false)
protected JAXBElement<String> uidBranch;
@XmlElementRef(name = "PWD", namespace = "http://schemas.datacontract.org/2004/07/...", type = JAXBElement.class, required = false)
protected JAXBElement<String> pwd;
@XmlElementRef(name = "Signature", namespace = "http://schemas.datacontract.org/2004/07/...", type = JAXBElement.class, required = false)
protected JAXBElement<String> signature;
... the rest: getters/setters
在请求中,这种类型的元素恰好如下所示:
<ns2:Credentials>
<ns4:string>login</ns4:string>
<ns4:string>password</ns4:string>
<ns4:string>signature</ns4:string>
</ns2:Credentials>
但是它丢失了类型内部元素的名称,上面的片段应该是这样的:
<ns2:Credentials>
<ns4:UID>login</ns4:UID>
<ns4:PWD>password</ns4:PWD>
<ns4:Signature>signature</ns4:Signature>
</ns2:Credentials>
为什么会这样以及如何强制客户以正确的方式行事?
更新
Credentials 对象是这样创建的(of
是 ObjectFactory
):
Credential cr = of.createCredential()
cr.setUID(of.createString(login))
cr.setPWD(of.createString(password))
cr.setSignature(of.createString(sign))
你得到
<ns4:string>login</ns4:string>
因为您使用 of.createString(login)
。如果你想要 ns4:UID
.
,请使用 of.createUID(...)
之类的东西
问题是,JAXBElement<String>
有一个字符串值(例如登录),还有元素的名称(分别为 getValue()
和 getName()
)。这个名字就是 XML 元素的名字。 wsimport
/xjc
生成的 ObjectFactory
通常包含生成此类 JAXBElement
实例的方法。这些 createFoo
方法将值作为输入并将它们包装在 JAXBElement
中,并使用相应的 XML 名称。所以当你使用 createString
时,你实际上是说你想要 string
作为元素名称。 createString
中的 String
用于元素名称,而不是值类型。
所以你的 ObjectFactory
也应该有 createUID
、createPWD
、createSignature
等方法。使用这些方法而不是 createString
。
顺便问一下,你真的调试过吗?如果您看过 ObjectFactory
的源代码,整个故事就会很明显,有什么理由避免这样做吗?
我有一个 WSDL 规范,使用 wsimport
生成客户端代码。 (就像我之前做过很多次一样)。
现在,xsd中的一种类型:
<xs:complexType name="Credential">
<xs:sequence>
<xs:element minOccurs="0" name="UID" nillable="true" type="xs:string"/>
<xs:element minOccurs="0" name="UIDBranch" nillable="true" type="xs:string"/>
<xs:element minOccurs="0" name="PWD" nillable="true" type="xs:string"/>
<xs:element minOccurs="0" name="Signature" nillable="true" type="xs:string"/>
</xs:sequence>
</xs:complexType>
和对应的java绑定:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Credential", namespace = "http://schemas.datacontract.org/2004/07/...", propOrder = {
"uid",
"uidBranch",
"pwd",
"signature"
})
public class Credential {
@XmlElementRef(name = "UID", namespace = "http://schemas.datacontract.org/2004/07/...", type = JAXBElement.class, required = false)
protected JAXBElement<String> uid;
@XmlElementRef(name = "UIDBranch", namespace = "http://schemas.datacontract.org/2004/07/...", type = JAXBElement.class, required = false)
protected JAXBElement<String> uidBranch;
@XmlElementRef(name = "PWD", namespace = "http://schemas.datacontract.org/2004/07/...", type = JAXBElement.class, required = false)
protected JAXBElement<String> pwd;
@XmlElementRef(name = "Signature", namespace = "http://schemas.datacontract.org/2004/07/...", type = JAXBElement.class, required = false)
protected JAXBElement<String> signature;
... the rest: getters/setters
在请求中,这种类型的元素恰好如下所示:
<ns2:Credentials>
<ns4:string>login</ns4:string>
<ns4:string>password</ns4:string>
<ns4:string>signature</ns4:string>
</ns2:Credentials>
但是它丢失了类型内部元素的名称,上面的片段应该是这样的:
<ns2:Credentials>
<ns4:UID>login</ns4:UID>
<ns4:PWD>password</ns4:PWD>
<ns4:Signature>signature</ns4:Signature>
</ns2:Credentials>
为什么会这样以及如何强制客户以正确的方式行事?
更新
Credentials 对象是这样创建的(of
是 ObjectFactory
):
Credential cr = of.createCredential()
cr.setUID(of.createString(login))
cr.setPWD(of.createString(password))
cr.setSignature(of.createString(sign))
你得到
<ns4:string>login</ns4:string>
因为您使用 of.createString(login)
。如果你想要 ns4:UID
.
of.createUID(...)
之类的东西
问题是,JAXBElement<String>
有一个字符串值(例如登录),还有元素的名称(分别为 getValue()
和 getName()
)。这个名字就是 XML 元素的名字。 wsimport
/xjc
生成的 ObjectFactory
通常包含生成此类 JAXBElement
实例的方法。这些 createFoo
方法将值作为输入并将它们包装在 JAXBElement
中,并使用相应的 XML 名称。所以当你使用 createString
时,你实际上是说你想要 string
作为元素名称。 createString
中的 String
用于元素名称,而不是值类型。
所以你的 ObjectFactory
也应该有 createUID
、createPWD
、createSignature
等方法。使用这些方法而不是 createString
。
顺便问一下,你真的调试过吗?如果您看过 ObjectFactory
的源代码,整个故事就会很明显,有什么理由避免这样做吗?