web-dev-qa-db-ja.com

SOAP WS-@WebParamをオプションにする

JAX-WSアノテーションによってWS APIで使用する非常に簡単なメソッドがあります。

@WebMethod
public MyResponse sendSingle2(
    @WebParam(name="username") String username,
    @WebParam(name="password") String password,
    @WebParam(name="newParam") String newParam) {
        // the code
    }

ここで、newParamをオプションにする必要があります。渡されたxmlのパラメーターが空の場合だけでなく、メソッドが引き続き機能することを意味します。

<ws:sendSingle2>
    <username>user</username>
    <password>pass</password>
    <newParam></newParam>
</ws:sendSingle2>

存在しない場合も:

<ws:sendSingle2>
    <username>user</username>
    <password>pass</password>
</ws:sendSingle2>

新しいパラメーターなしで動作する既存のAPIを壊さないようにする必要があります。

14
amorfis

@WebParamは、メッセージパーツをパラメーターにマップします。パーツをオプションにすることはできません。 WSDLのオプションのメッセージ部分 を参照してください。したがって、短い答えは、正確にあなたが求めていることはできないということです。ただし、このメソッドをリファクタリングできる場合は、以下で説明する方法のいずれかを使用できます。

通常、パラメーターのオプションはスキーマ_minOccurs=0_を介して設定されます。さらに、複数のパラメーターを使用する代わりに、WebMethodのパラメーターとして定義するスキーマに1つのRequestパラメーターを定義できます。オプション性はパラメータ内にカプセル化され、オプションのパラメータの有無にかかわらず同じメソッドが呼び出しに対して呼び出されます。

自動生成されたファイルに依存するのではなく、最初に契約を定義することを好みます。 XSD、SOAPとWSDLが一体となってどのように動作するかを理解したら、注釈/コードファーストベースの定義を使用することはほとんどありません。

コード例:

_<xs:schema
    targetNamespace="http://your.namespace.com"
    xmlns:tns="http://your.namespace.com"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    elementFromDefault="qualified"
    attributeFromDefault="qualified">

...

<xs:element name="MyRequest" type="tns:MyRequestType" />
<xs:element name="MyResponse" type="tns:MyResponseType" />

<xs:complexType name"MyRequestType">
    <xs:sequence>
        <xs:element name="username" type="xs:string" minOccurs="1" maxOccurs="1" />
        <xs:element name="password" type="xs:string" minOccurs="1" maxOccurs="1" />
        <xs:element name="newParam" type="xs:string" minOccurs="0" maxOccurs="1" />
    </xs:sequence>
</xs:complexType>

...

</xs:schema>
_

WSDLファイルで、次のようなメッセージを定義します。

_<wsdl:definitions
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    xmlns:msg="http://your.namespace.com"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
    targetNamespace="http://your.namespace.com">

    <wsdl:types>
        <xs:schema>
            <!-- either import the externalized schema -->
            <xs:import namespace="http://your.namespace.com"
                       schemaLocation="someDir/yourMessageSchema.xsd" />
        </xs:schema>
        <!-- or define the schema within the WSDL - just copy the schema here -->
        <xs:schema
            targetNamespace="http://your.namespace.com"
            xmlns:tns="http://your.namespace.com"
            xmlns:xs="http://www.w3.org/2001/XMLSchema"
            elementFromDefault="qualified"
            attributeFromDefault="qualified">
                ...
        </xs:schema>
    </wsdl:types>

    ...

    <wsdl:message name="sendSingle2Request">
        <wsdl:part name="in" element="msg:MyRequest" />
    </wsdl:message>

    <wsdl:message name="sendSingle2Response">
        <wsdl:part name="out" element="msg:MyResponse" />
    </wsdl:message>

    ...

    <wsdl:portType name="YourServiceEndpoint">
        <wsdl:operation name="sendSingle2">
            <wsdl:input message="tns:sendSingle2Request" />
            <wsdl:output message="tns:sendSingle2Response" />
        </wsdl:operation>
        ...
    </wsdl:portType>

    <wsdl:binding name="YourServiceBinding" type="YourServiceEndpoint">
        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
        <wsdl:operation name=""sendSingle2">
            <soap:operation soapAction="http://your.namespace.com/SendSingle2" style="document" />
            <wsdl:input>
                <soap:body parts="in" use="literal" />
            </wsdl:input>
            <wsdl:output>
                <soap:body parts="out" use="literal" />
            </wsdl:output>
        </wsdl:operation>
        ...
    </wsdl:binding>

    <wsdl:service name="YourService">
        <wsdl:port name="YourServicePort binding="tns:YourServiceBinding">
            <soap:address location="http://your.server:port/path/to/the/service" />
        </wsdl:port>
    </wsdl:service>
</wsdl:definitions>
_

ここでのWSDLコントラクトは、スタイルを使用することを定義します:_document/literal_そしてスキーマの助けにより、実際のSOAP=メッセージは_document/literal wrapped_になり、さらにWS-Iに準拠します。

したがって、メソッドはpublic MyResponse sendSinge2(MyRequest request)に変わります。ここで、requestusernamepassowrd、およびnewParamをカプセル化します。 newParamがSOAPリクエストで送信されなかった場合、nullを返すだけなので、使用する前に最初に確認してください。

コードファーストのアプローチに固執する場合は、最初にMyRequestクラスを定義する必要があります。これは、これらの2つまたは3つの値ではなく、リクエストパラメーターとして使用します。

_@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "MyRequest", namespace="http://your.namespace.com")
public class MyRequest implements Serializable
{
   @XmlElement(name = "username", required = true)
   protected String username;
   @XmlElement(name = "password", required = true)
   protected String password;
   @XmlElement(name = "newParam", required = false)
   protected String newParam;
   ...
}
_

まだ行っていない場合は、MyResultにも同じことを行う必要があります。 Webメソッドは次のようになります。

_@WebMethod(operationName = "sendSingle2")
@WebResult(name = "sendSingle2Response", targetNamespace = "http://your.namespace.com")
public MyResult sendSingle2(@WebParam(name = "sendSingle2Request") MyRequest request)
{
   ...
}
_

繰り返しますが、requestは3つのパラメーターをカプセル化します。オプションのパラメーターがnullかどうかを最初に確認する必要があります。

HTH

16
Roman Vottner

これらはすべて、これらのパラメーターを使用している実装クラスに依存します。エンドポイントインターフェイスで、このパラメーターをwebparamとして追加するだけです。

実装クラスで確認してくださいこのパラメーターをどこかで使用している場合は、代替パラメーター(他の部分)を追加して、このパラメーターなしで操作または実行を実行してください。

推奨されるように実装クラスでそれらを検証または使用しない限り、すべてのパラメーターはオプションとして扱われると思います。

0
kingAm