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 对象是这样创建的(ofObjectFactory):

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 也应该有 createUIDcreatePWDcreateSignature 等方法。使用这些方法而不是 createString

顺便问一下,你真的调试过吗?如果您看过 ObjectFactory 的源代码,整个故事就会很明显,有什么理由避免这样做吗?