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>

以下は、wsimport によって生成されたコードを含む、この Web サービスを実装する Java コードです。

@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/ "、local:"paramName")。期待される要素は <{ http://companyname.org/ }paramName>,<{}paramValue> です

JAXB は、http://companyname.org/adapter1/名前空間で定義された paramName 置換を認識していないようです。しかし、なぜ JAXB がそのような振る舞いをするのか、私には想像できません。私の間違いはどこですか?何か案は?

4

1 に答える 1

0

あなたはすでに答えを知っています: http://companyname.org/adapter1はhttp://companyname.org/と同じではありません。

生成されたソースは、要素がhttp://companyname.org/名前空間で次の行でparamName 定義されていることを明示的に示しています。

@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 に答える