11

次のように、SOAP本文にプレフィックスを渡さずにクライアントがWebサービスを呼び出している場合、私のWebサービスはクライアントの要求を処理できません。

<soap:Body> 
 <GetPatientResultsRequest xmlns="http://urlA"> 
  <PatientIdentification> 
      <PersonCivilRegistrationIdentifier xmlns="http://UrlB"/> 
  </PatientIdentification> 
  <Period> 
    <From>2012-05-26</From> 
     <To>2012-06-26</To> 
   </Period> 
 </GetPatientResultsRequest> 
</soap:Body>

エラーは、およびその他に対応するJavaオブジェクトGetPatientResultsRequestがnullであるということです。

Bodyにプレフィックスがない場合、逆シリアル化が適切に行われていないようです。私のWebサービスは、SOAP本文に次のようなプレフィックスが付いている場合にのみ応答できます。

<soap:Body> 
 <m:GetPatientResultsRequest xmlns:m="http://urlA">
  <PatientIdentification> 
      <PersonCivilRegistrationIdentifier xmlns="http://UrlB"/> 
  </PatientIdentification> 
  <Period> 
    <From>2012-05-26</From> 
     <To>2012-06-26</To> 
   </Period> 
 </m:GetPatientResultsRequest> 
</soap:Body>

私のWebサービスがすべての種類のSOAPリクエスト(つまり、Bodyにプレフィックスがある場合とない場合)を受け取ることができるようにするために、誰かが私に何をすべきか教えてもらえますか?

JAX-WS(SOAP 1.1)を使用しています

4

1 に答える 1

11

Web サービスは、それを呼び出すために従わなければならない契約を定義します。投稿した例からのメッセージは 1 つだけがそのコントラクトに一致するため、一方は機能し、もう一方は機能しません。

最初のメッセージでは、(ラッパーの属性のため) デフォルトの名前空間を定義し、xmlnsそれを宣言解除せず、プレフィックスを持たないすべての要素は、親から継承するため、同じ名前空間にあります。

2番目のメッセージでは、明示的なプレフィックス宣言があり、ラッパーのみがその名前空間にあり、他の要素は名前空間になく、親からデフォルトのものを継承しません(xmlns属性が欠落しているため)。

冒頭で述べたように、Web サービスはコントラクトを定義します。クライアントからの誤ったメッセージを受け入れるようにサービスを変更するのではなく、正しいメッセージを送信するようにクライアントを変更する方が理にかなっています。

要素の名前空間を制御するには、Web サービスとクライアントtargetNamespaceの JAX-WS アノテーションの値を使用する必要があります。

ターゲット名前空間を変更した場合のコードとメッセージ形式の違いを確認する例を次に示します。これには基本的な WSDL を使用します。

<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions 
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
xmlns:tns="http://tempuri.org" 
xmlns:xs="http://www.w3.org/2001/XMLSchema" 
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
targetNamespace="http://tempuri.org" 
name="CalculatorWS">
  <wsdl:types>
    <xs:schema targetNamespace="http://tempuri.org">
      <xs:element name="add" type="tns:add" />
      <xs:element name="addInput" type="tns:addInput" />
      <xs:element name="addResponse" type="tns:addResponse" />
      <xs:element name="addOutput" type="tns:addOutput" />
      <xs:complexType name="add">
        <xs:sequence>
          <xs:element name="addInput" type="tns:addInput" />
        </xs:sequence>
      </xs:complexType>
      <xs:complexType name="addInput">
        <xs:sequence>
          <xs:element name="a" type="xs:int" />
          <xs:element name="b" type="xs:int" />
        </xs:sequence>
      </xs:complexType>
      <xs:complexType name="addResponse">
        <xs:sequence>
          <xs:element name="addOutput" type="tns:addOutput" />
        </xs:sequence>
      </xs:complexType>
      <xs:complexType name="addOutput">
        <xs:sequence>
          <xs:element name="result" type="xs:int" />
        </xs:sequence>
      </xs:complexType>
    </xs:schema>
  </wsdl:types>
  <wsdl:message name="add">
    <wsdl:part name="parameters" element="tns:add" />
  </wsdl:message>
  <wsdl:message name="addResponse">
    <wsdl:part name="parameters" element="tns:addResponse" />
  </wsdl:message>
  <wsdl:portType name="CalculatorWS">
    <wsdl:operation name="add">
      <wsdl:input message="tns:add" />
      <wsdl:output message="tns:addResponse" />
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="CalculatorWSPortBinding" type="tns:CalculatorWS">
    <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" />
    <wsdl:operation name="add">
      <soap:operation soapAction="http://tempuri.org/add" />
      <wsdl:input>
        <soap:body use="literal" />
      </wsdl:input>
      <wsdl:output>
        <soap:body use="literal" />
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="CalculatorWSService">
    <wsdl:port name="CalculatorWSPort" binding="tns:CalculatorWSPortBinding">
      <soap:address location="http://localhost:8080/WebServices/CalculatorWS" />
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

これは、次のようなメッセージを定義します:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
        xmlns:tem="http://tempuri.org">
   <soapenv:Body>
      <tem:add>
         <addInput>
            <a>?</a>
            <b>?</b>
         </addInput>
      </tem:add>
   </soapenv:Body>
</soapenv:Envelope>

と:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
       xmlns:tem="http://tempuri.org">
   <soapenv:Body>
      <tem:addResponse>
         <addOutput>
            <result>?</result>
         </addOutput>
      </tem:addResponse>
   </soapenv:Body>
</soapenv:Envelope>

ラッパーの名前空間プレフィックスを参照してください。これは、要素がhttp://tempuri.org名前空間で宣言されているのに対し、他の要素は名前空間で宣言されておらず、名前空間にも含まれていないためです。

名前空間からすべての要素を削除することもできます。WSDL から対象の名前空間を取り除き、次のようにします。

<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions 
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
xmlns:xs="http://www.w3.org/2001/XMLSchema" 
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
name="CalculatorWS">
  <wsdl:types>
    <xs:schema>
      <xs:element name="add" type="add" />
      <xs:element name="addInput" type="addInput" />
      <xs:element name="addResponse" type="addResponse" />
      <xs:element name="addOutput" type="addOutput" />
      <xs:complexType name="add">
        <xs:sequence>
          <xs:element name="addInput" type="addInput" />
        </xs:sequence>
      </xs:complexType>
      <xs:complexType name="addInput">
        <xs:sequence>
          <xs:element name="a" type="xs:int" />
          <xs:element name="b" type="xs:int" />
        </xs:sequence>
      </xs:complexType>
      <xs:complexType name="addResponse">
        <xs:sequence>
          <xs:element name="addOutput" type="addOutput" />
        </xs:sequence>
      </xs:complexType>
      <xs:complexType name="addOutput">
        <xs:sequence>
          <xs:element name="result" type="xs:int" />
        </xs:sequence>
      </xs:complexType>
    </xs:schema>
  </wsdl:types>
  <wsdl:message name="add">
    <wsdl:part name="parameters" element="add" />
  </wsdl:message>
  <wsdl:message name="addResponse">
    <wsdl:part name="parameters" element="addResponse" />
  </wsdl:message>
  <wsdl:portType name="CalculatorWS">
    <wsdl:operation name="add">
      <wsdl:input message="add" />
      <wsdl:output message="addResponse" />
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="CalculatorWSPortBinding" type="CalculatorWS">
    <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" />
    <wsdl:operation name="add">
      <soap:operation soapAction="http://tempuri.org/add" />
      <wsdl:input>
        <soap:body use="literal" />
      </wsdl:input>
      <wsdl:output>
        <soap:body use="literal" />
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="CalculatorWSService">
    <wsdl:port name="CalculatorWSPort" binding="CalculatorWSPortBinding">
      <soap:address location="http://localhost:8080/WebServices/CalculatorWS" />
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

この新しい WSDL は、次のようなメッセージに対応します。

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Body>
      <add>
         <addInput>
            <a>?</a>
            <b>?</b>
         </addInput>
      </add>
   </soapenv:Body>
</soapenv:Envelope>

と:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Body>
      <addResponse>
         <addOutput>
            <result>?</result>
         </addOutput>
      </addResponse>
   </soapenv:Body>
</soapenv:Envelope>

この場合、プレフィックスはありません。

wsimport.exe両方の WSDL で使用すると、最初に説明したターゲット名前空間が表示されます。つまり、次のように変更されています。

@WebService(name = "CalculatorWS", targetNamespace = "http://tempuri.org")
public interface CalculatorWS {
    @WebMethod(action = "http://tempuri.org/add")
    @WebResult(name = "addOutput", targetNamespace = "")
    @RequestWrapper(localName = "add", targetNamespace = "http://tempuri.org", className = "your.pack.age.Add")
    @ResponseWrapper(localName = "addResponse", targetNamespace = "http://tempuri.org", className = "your.pack.age.AddResponse")
    public AddOutput add(
        @WebParam(name = "addInput", targetNamespace = "")
        AddInput addInput);
}

これに:

@WebService(name = "CalculatorWS", targetNamespace = "")
public interface CalculatorWS {
    @WebMethod(action = "http://tempuri.org/add")
    @WebResult(name = "addOutput", targetNamespace = "")
    @RequestWrapper(localName = "add", targetNamespace = "", className = "your.pack.age.Add")
    @ResponseWrapper(localName = "addResponse", targetNamespace = "", className = "your.pack.age.AddResponse")
    public AddOutput add(
        @WebParam(name = "addInput", targetNamespace = "")
        AddInput addInput);
}

を制御するtargetNamespaceと、メッセージの外観を制御できます。

于 2012-09-05T21:09:16.367 に答える