Powered by SmartDoc

WSDL

WSDLとSOAP-RPC

WSDLは、Web Services Description Languageの略です。WSDLは、文字通りWebサービスの記述のための言語なのですが、この講座ではWSDLを、SOAP-RPCとしてのWebサービスを記述する言語として捉えていこうと考えています。厳密に言えば、すぐ後で見るようにRequest/Responseを用いるRPCだけでなく、One-Way型のメッセージングによるWebサービスの記述もWSDLでは可能です。ただ、それはRPCの記述の自然な拡大として理解できることです。WSDLを基本的にはSOAP-RPCの記述として捉えることは、SOAP-RPCからJAX-RPCへの発展を考える上でも、JavaとWSDLとの相互関係を理解する上でも重要なことだと思います。

WSDLを一通りながめる

先のCalculatorを記述するWSDLを、いろいろな角度から眺めてみましょう。まずは、簡単にわかる表面的なことですが、次のことを確認してみてください。

  1. WSDL全体は、<definitions>…..</definitions>のタグで囲まれています。複数形であることに注意してください。
  2. 要素には、たくさんのNameSpaceの定義がついています。
  3. definitions要素の内部で、かつ一番外側の要素には、次のような要素があります。

今度は、このWSDLのサンプルで、もう少し詳しい中身、それぞれの名前をもつ要素が相互に関係しあっていることを見てみることにしましょう。

  1. message要素の名前たち、addResponse, addRequest….は、次のportType要素中のoperation要素のinput, output要素中に、次のような形で登場しています。<wsdl:input message="impl:addRequest" name="addRequest" />
  2. portType要素の名前Calculatorは、binding要素に次のように使われています。

    <wsdl:binding name="CalculatorSoapBinding" type="impl:Calculator">

  3. 同じく、binding要素の名前CalculatorSoapBindingは、次のservice要素の中に次のように現れます。

    <wsdl:port binding="impl:CalculatorSoapBinding"……>

こうして、ファイル中で前に登場する要素たちが、ファイルの後の要素たちの中で利用されている関係があることがわかります。これは、最後のservice要素には、先行するすべての要素の情報が流れ込んでいることを意味しています。WSDLは、やはり、Serviceの記述なのですね。

WSDLサンプル
<?xml version="1.0" encoding="UTF-8" ?>
<wsdl:definitions targetNamespace="http://localhost:8080/axis/Calculator.jws"
 xmlns="http://schemas.xmlsoap.org/wsdl/"
 xmlns:apachesoap="http://xml.apache.org/xml-soap"
 xmlns:impl="http://localhost:8080/axis/Calculator.jws"
 xmlns:intf="http://localhost:8080/axis/Calculator.jws"
 xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
 xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
 xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"
 xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <wsdl:message name="subtractRequest">
    <wsdl:part name="i1" type="xsd:int" />
    <wsdl:part name="i2" type="xsd:int" />
  </wsdl:message>
  <wsdl:message name="subtractResponse">
    <wsdl:part name="subtractReturn" type="xsd:int" />
  </wsdl:message>
  <wsdl:message name="addResponse">
    <wsdl:part name="addReturn" type="xsd:int" />
  </wsdl:message>
  <wsdl:message name="addRequest">
    <wsdl:part name="i1" type="xsd:int" />
    <wsdl:part name="i2" type="xsd:int" />
  </wsdl:message>
  <wsdl:portType name="Calculator">
    <wsdl:operation name="add" parameterOrder="i1 i2">
      <wsdl:input message="impl:addRequest" name="addRequest"/>
      <wsdl:output message="impl:addResponse" name="addResponse"/>
    </wsdl:operation>
    <wsdl:operation name="subtract" parameterOrder="i1 i2">
      <wsdl:input message="impl:subtractRequest" name="subtractRequest"/>
      <wsdl:output message="impl:subtractResponse" name="subtractResponse"/>
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="CalculatorSoapBinding" type="impl:Calculator">
    <wsdlsoap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="add">
      <wsdlsoap:operation soapAction="" />
      <wsdl:input name="addRequest">
        <wsdlsoap:body
        encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
        namespace="http://localhost:8080/axis/Calculator.jws" use="encoded"/>
      </wsdl:input>
      <wsdl:output name="addResponse">
        <wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
        namespace="http://localhost:8080/axis/Calculator.jws" use="encoded"/>
      </wsdl:output>
    </wsdl:operation>
    <wsdl:operation name="subtract">
      <wsdlsoap:operation soapAction="" />
      <wsdl:input name="subtractRequest">
        <wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
        namespace="http://localhost:8080/axis/Calculator.jws" use="encoded"/>
      </wsdl:input>
      <wsdl:output name="subtractResponse">
        <wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
        namespace="http://localhost:8080/axis/Calculator.jws" use="encoded"/>
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="CalculatorService">
    <wsdl:port binding="impl:CalculatorSoapBinding" name="Calculator">
      <wsdlsoap:address location="http://localhost:8080/axis/Calculator.jws"/>
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

SOAP-RPCの記述としてのWSDL ―― WSDLをうしろから読む

それなら、WSDLを最後に定義されているservice要素から、前のほうに向かって読んでいくこともできるはずです。一つづつ見ていきましょう。(もっとも、これは慣例的に用いられる要素の流れに従っているまでで、WSDLの中で要素の順序は意味を持たないはずでです。)

service

service要素は、URLのlocation属性を抱えたaddress要素を含む、port要素から構成されている、比較的、簡単な形をしています。このURLは、Webサービスを提供するサーバとサービスのEndpointの指定です。このサービスのURL以外の具体的な情報は、port要素のbinding属性で参照されている、binding要素の情報に記述されているということです。

binding

binding要素には、それでは、どのような情報が含まれているのでしょうか。結構、複雑な形をしていますね。繰り返しになりますが、もう一度確認したいことは、このbinding要素のname属性は、先に見たようにservice要素のport要素のbinding属性で参照されており、また、このbinding要素のtype属性は、先行するportTypeのname属性の値に他なりません。

次のSOAPのnamespaceを持つbinding要素は、このWebサービスがRPCスタイルのサービス呼び出しを行い、transport層は、HTTPを使うことを意味しています。

<wsdlsoap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>

実際には、ほとんどのWebサービスがRPC型で、HTTPを使っているのですが、それはこうした形で、WSDLの内部で宣言されていなければなりません。ここのbinding styleの部分が、たとえば、次のようになっていれば、

<soap:binding style="document" transport="http://example.com/smtp"/>

RPCではなく一方向のメッセージングで、トランスポート層には、SMTPを使うということを意味します。同じoperationの定義でも、binding styleやencodingStyleを変えれば、異なった実装がされることになるわけです。ここでは、このbinding要素が、WSDL本体のbinding要素とは、NameSpaceが異なることに留意してください。RPCやHTTPを指定しているのは、WSDLのbindingではなく、SOAPのbinding要素だということです。

binding要素の大部分は、operationの定義にあてられています。この例では、addとsubtractという二つのoperationが定義されています。operationは、inputとoutputの定義から構成されています。WSDLのoperationは、SOAP-RPCで呼びだされる操作、Javaのメソッドに対応するものです。Inputはメソッドの引数、outputはメソッドの返り値と考えればいいと思います。この点では、次に見る、portTypeでのoperationの定義と共通しています。それでは、binding要素中でのoperationの定義と、portType要素中でのoperationの定義の違いは、どこにあるのか考えてみてください。binding要素の中では、実際にやり取りされるSOAPメッセージのBody部分に埋め込まれるencodingStyleやnamespaceが定義されています。Body要素のNamesSpaceがSOAPになっていることに注意してください。その点では、bindingでのoerationの定義は、portTypeでのoperationの定義より、実装に近い具体的なものだと考えることができます。

portType

portTypeタグは、operationを定義しています。先にも触れたように、bindingタグでのoperationの定義とportTypeタグでのoperationの定義は、一対一に対応しています。同一のoperationを、bindingとportTypeとは違ったレベルで定義しているのです。portTypeでは、operationのinputとoutputは、SOAPメッセージのencodingStyleやnamespaceといった具体的な情報によってではなく、それを構成するメッセージそのもの、抽象的なレベルでのメッセージの型によって定義されています。operationのinputとoutputは、RPCのメソッドの引数と返り値に対応しますので、portTypeタグは、メソッドの引数と返り値に、それぞれの型を対応付けていると考えることができます。ですから、bindingでのoperationの定義が、関数の実装、メソッドの実装に対応すると考えれば、portTypeでのoperationの定義は、関数のプロトタイプ定義、メソッドのインターフェース定義に相当すると考えることが可能です。

message

messageの名前は、portTypeでのoperaton定義のinput、outputの中で利用されます。messageタグは、partタグを抱えています。そしてpartタグは、名前属性と型属性を持っています。

このサンプルでは、この型属性が、type="xsd:int"のような形で、schemaのNameSpaceをしめすxsdで修飾されていることに注意してください。

types

先の例には登場していなかったのですが、WSDLの中で大事な働きをするタグが一つ残っています。それが、typesタグです。typesタグは、Schemaを利用して新しい型を定義して、その型をWSDLで使うことを可能とします。typesタグとmessageタグは、新しい型のワイアリング・フォーマット、ネットワーク上に実際にどのような形のメッセージが流れるかを規定します。次の章では、そのことを、実例を挙げて見ることにしましょう。