2

这是一个包含名为 paramName 的抽象全局元素的 WSDL:

   <wsdl:definitions name="AdapterSessionManagerService" targetNamespace="http://companyname.org/" xmlns:ns1="http://schemas.xmlsoap.org/soap/http" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:tns="http://companyname.org/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <wsdl:types>
      <xs:schema elementFormDefault="unqualified" targetNamespace="http://companyname.org/" version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <import namespace="http://companyname.org/adapter1/" schemaLocation="http://localhost:8081/adapters/AdapterSessionManager?xsd=adapter1/ElementName.xsd"/>
    <import namespace="http://companyname.org/adapter2/" schemaLocation="http://localhost:8081/adapters/AdapterSessionManager?xsd=adapter2/ElementName.xsd"/>

         <xs:element name="initAdapterSession" type="tns:initAdapterSession"/>
         <xs:element name="initAdapterSessionResponse" type="tns:initAdapterSessionResponse"/>
         <xs:complexType name="initAdapterSession">
            <xs:sequence>
               <xs:element name="adapterId" type="xs:long"/>
               <xs:element name="callbackURL" type="xs:anyURI"/>
               <xs:element name="adapterInputData" type="tns:AdapterInputDataType"/>
            </xs:sequence>
         </xs:complexType>
         <xs:complexType name="initAdapterSessionResponse">
            <xs:sequence>
               <xs:element minOccurs="0" name="return" type="xs:long"/>
            </xs:sequence>
         </xs:complexType>
         <xs:complexType name="AdapterInputDataType">
            <xs:sequence>
               <xs:element maxOccurs="unbounded" minOccurs="0" name="atomicParam" type="tns:AtomicParamType"/>
            </xs:sequence>
         </xs:complexType>
         <xs:complexType name="AtomicParamType">
            <xs:sequence>
               <xs:element maxOccurs="1" minOccurs="1" ref="tns:paramName"/>
               <xs:element maxOccurs="1" minOccurs="1" name="paramValue" type="tns:AtomicParamValueType"/>
            </xs:sequence>
         </xs:complexType>
         <xs:simpleType name="AtomicParamValueType">
            <xs:union memberTypes="xs:string xs:long xs:decimal xs:dateTime xs:boolean"/>
         </xs:simpleType>
         <xs:element abstract="true" name="paramName" type="xs:string"/>
      </xs:schema>
   </wsdl:types>
   <wsdl:message name="initAdapterSessionResponse">
      <wsdl:part element="tns:initAdapterSessionResponse" name="parameters"/>
   </wsdl:message>
   <wsdl:message name="initAdapterSession">
      <wsdl:part element="tns:initAdapterSession" name="parameters"/>
   </wsdl:message>
   <wsdl:portType name="AdapterSessionManager">
      <wsdl:operation name="initAdapterSession">
         <wsdl:input message="tns:initAdapterSession" name="initAdapterSession"/>
         <wsdl:output message="tns:initAdapterSessionResponse" name="initAdapterSessionResponse"/>
      </wsdl:operation>
   </wsdl:portType>
   <wsdl:binding name="AdapterSessionManagerServiceSoapBinding" type="tns:AdapterSessionManager">
      <soap12:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
      <wsdl:operation name="initAdapterSession">
         <soap12:operation soapAction="" style="document"/>
         <wsdl:input name="initAdapterSession">
            <soap12:body use="literal"/>
         </wsdl:input>
         <wsdl:output name="initAdapterSessionResponse">
            <soap12:body use="literal"/>
         </wsdl:output>
      </wsdl:operation>
   </wsdl:binding>
   <wsdl:service name="AdapterSessionManagerService">
      <wsdl:port binding="tns:AdapterSessionManagerServiceSoapBinding" name="AdapterSessionManagerPort">
         <soap12:address location="http://localhost:8081/adapters/AdapterSessionManager"/>
      </wsdl:port>
   </wsdl:service>
</wsdl:definitions>

此元素旨在用在另一个名称空间中定义的相同命名元素替换 SOAP 消息。以下是此类定义的示例:

<schema targetNamespace="http://companyname.org/adapter1/" xmlns="http://www.w3.org/2001/XMLSchema" xmlns:inptypns="http://companyname.org/" xmlns:tns="http://companyname.org/adapter1/">
   <import namespace="http://companyname.org/"/>
   <element name="paramName" substitutionGroup="inptypns:paramName" type="tns:AtomicParamNameType"/>
   <simpleType name="AtomicParamNameType">
      <restriction base="string">
         <enumeration value="foo"/>
         <enumeration value="bar"/>
      </restriction>
   </simpleType>
</schema>

这是实现此 Web 服务的 Java 代码,包括由 wsimport 生成的代码:

@WebService(wsdlLocation = "WEB-INF/wsdl/AdapterSessionManager.wsdl")
@BindingType(SOAPBinding.SOAP12HTTP_BINDING)
public class AdapterSessionManager {

    @WebMethod
    public Long initAdapterSession(
            @WebParam(name = "adapterId")
            @XmlElement(required = true)
            Long adapterId,

            @WebParam(name = "callbackURL")
            @XmlElement(required = true)
            URL callbackURL,

            @WebParam
            @XmlElement(required = true)
            AdapterInputDataType adapterInputData
    ) {...}
}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "AdapterInputDataType", propOrder = {
    "atomicParam"
})
public class AdapterInputDataType {

    protected List<AtomicParamType> atomicParam;

    public List<AtomicParamType> getAtomicParam() {
        if (atomicParam == null) {
            atomicParam = new ArrayList<AtomicParamType>();
        }
        return this.atomicParam;
    }

}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "AtomicParamType", propOrder = {
    "paramName",
    "paramValue"
})
public class AtomicParamType {

    @XmlElementRef(name = "paramName", namespace = "http://companyname.org/", type = JAXBElement.class)
    protected JAXBElement<?> paramName;
    @XmlElement(required = true)
    protected String paramValue;

    public JAXBElement<?> getParamName() {
        return paramName;
    }

    public void setParamName(JAXBElement<?> value) {
        this.paramName = value;
    }

    public String getParamValue() {
        return paramValue;
    }

    public void setParamValue(String value) {
        this.paramValue = value;
    }
}

@XmlRegistry
public class ObjectFactory {

    private final static QName _ParamName_QNAME = new QName("http://companyname.org/", "paramName");

    public ObjectFactory() {
    }

    public AtomicParamType createAtomicParamType() {
        return new AtomicParamType();
    }

    public AdapterInputDataType createAdapterInputDataType() {
        return new AdapterInputDataType();
    }

    @XmlElementDecl(namespace = "http://companyname.org/", name = "paramName")
    public JAXBElement<String> createParamName(String value) {
        return new JAXBElement<String>(_ParamName_QNAME, String.class, null, value);
    }
}

@XmlType(name = "AtomicParamNameType", namespace = "http://companyname.org/adapter1/")
@XmlEnum
public enum AtomicParamNameType {

    @XmlEnumValue("foo")
    FOO("foo"),
    @XmlEnumValue("bar")
    BAR("bar");
    private final String value;

    AtomicParamNameType(String v) {
        value = v;
    }

    public String value() {
        return value;
    }

    public static AtomicParamNameType fromValue(String v) {
        for (AtomicParamNameType c: AtomicParamNameType.values()) {
            if (c.value.equals(v)) {
                return c;
            }
        }
        throw new IllegalArgumentException(v);
    }

}

@XmlRegistry
public class ObjectFactory {

    private final static QName _ParamName_QNAME = new QName("http://companyname.org/adapter1/", "paramName");

    public ObjectFactory() {
    }

    @XmlElementDecl(namespace = "http://companyname.org/adapter1/", name = "paramName", substitutionHeadNamespace = "http://companyname.org/", substitutionHeadName = "paramName")
    public JAXBElement<AtomicParamNameType> createParamName(AtomicParamNameType value) {
        return new JAXBElement<AtomicParamNameType>(_ParamName_QNAME, AtomicParamNameType.class, null, value);
    }

}

我正在使用以下 SOAP 请求测试服务:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ws="http://companyname.org/" xmlns:ans="http://companyname.org/adapter1/">
   <soapenv:Header/>
   <soapenv:Body>
      <ws:initAdapterSession>
         <adapterId>123</adapterId>
         <callbackURL>http://callback</callbackURL>
         <adapterInputData>
            <atomicParam>
               <ans:paramName>foo</ans:paramName>
               <paramValue>hello</paramValue>
            </atomicParam>
         </adapterInputData>
      </ws:initAdapterSession>
   </soapenv:Body>
</soapenv:Envelope>

当应用程序服务器收到请求时,我有以下 UnmarshallException:

javax.xml.bind.UnmarshalException:意外元素(uri:“ http://companyname.org/adapter1/ ”,本地:“paramName”)。预期的元素是 <{ http://companyname.org/ }paramName>,<{}paramValue>

看起来 JAXB 不知道命名空间中定义的 paramName 替换http://companyname.org/adapter1/。但我无法想象为什么 JAXB 会以这种方式行事。我的错误在哪里?有任何想法吗?

4

1 回答 1

0

您已经知道答案:http://companyname.org/adapter1http://companyname.org/不同。

您生成的源代码明确表明该paramName 元素是在http://companyname.org/命名空间中定义的,其中包含以下行。

@XmlElementRef(name = "paramName", namespace = "http://companyname.org/", type = JAXBElement.class)
protected JAXBElement<?> paramName;

因此,将namespace属性更改http://companyname.org/adapter1为允许 JAXB 正确解组您的有效负载

于 2013-05-23T18:53:48.540 回答