では、WSDLの記述例として、
を持ち、Userinfoクラスとして、
を提供するWebサービスをとりあげてみよう。まず、ソースコードとしてJavaを使い、プログラムの例を示す。
Userid.java ---------------------------------- public class Userid { public String userid = ""; public String password = ""; } Userdata.java -------------------------------- public class Userdata { public String userid = ""; public String firstnm = ""; public String lastnm = ""; public String tel = ""; public int age = 0; } Userinfo.java -------------------------------- public class Userinfo { public boolean login(Userid userid) { return true; } public Userdata getUserdata(Userid u) { return null; } public boolean update(Userid u, Userdata d) { return true; } }
インターフェイス定義の説明なので、実装部分はまったく記述していないが気にしないでほしい。このプログラムをHTTP上のSOAP-RPCとして提供するためのWSDL定義を作成すると、以下のようになる。
<?xml version="1.0" encoding="UTF-8"?> <definitions name="Userinfo_Service" targetNamespace= "http://www.userinfoservice.com/Userinfo-interface" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://www.userinfoservice.com/Userinfo" xmlns:xsd="http://www.w3.org/1999/XMLSchema"> <types> <xsd:schema targetNamespace="http://www.userinfoservice.com/Userinfo" xmlns="http://www.w3.org/1999/XMLSchema/"> <xsd:complexType name="Userdata"> <xsd:element name="age" type="xsd:int"/> <xsd:element name="tel" type="xsd:string"/> <xsd:element name="lastnm" type="xsd:string"/> <xsd:element name="firstnm" type="xsd:string"/> <xsd:element name="userid" type="xsd:string"/> </xsd:complexType> <xsd:complexType name="Userid"> <xsd:element name="password" type="xsd:string"/> <xsd:element name="userid" type="xsd:string"/> </xsd:complexType> </xsd:schema> </types> <message name="InloginRequest"> <part name="meth1_inType1" type="tns:Userid"/> </message> <message name="OutloginResponse"> <part name="meth1_outType" type="xsd:boolean"/> </message> <message name="InupdateUserRequest"> <part name="meth2_inType1" type="tns:Userid"/> <part name="meth2_inType2" type="tns:Userdata"/> </message> <message name="OutupdateUserResponse"> <part name="meth2_outType" type="xsd:boolean"/> </message> <portType name="Userinfo_Service"> <operation name="login"> <input message="InloginRequest"/> <output message="OutloginResponse"/> </operation> <operation name="updateUser"> <input message="InupdateUserRequest"/> <output message="OutupdateUserResponse"/> </operation> </portType> <binding name="Userinfo_ServiceBinding" type="Userinfo_Service"> <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/> <operation name="login"> <soap:operation soapAction="urn:userinfo-service"/> <input> <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:userinfo-service" use="encoded"/> </input> <output> <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:userinfo-service" use="encoded"/> </output> </operation> <operation name="updateUser"> <soap:operation soapAction="urn:userinfo-service"/> <input> <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:userinfo-service" use="encoded"/> </input> <output> <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:userinfo-service" use="encoded"/> </output> </operation> </binding> </definitions>
上のファイルでは、types、message、portType、bindingのみが定義されている。しかし、これにはservice、portが定義されていないので、どこへアクセスすればよいかが分からない。次のWSDLファイルでは、前のファイルを<import>要素で取り込み、port情報を提供する。
<?xml version="1.0" encoding="UTF-8"?> <definitions name="Userinfo_Service" targetNamespace="http://www.userinfoservice.com/Userinfo" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://www.userinfoservice.com/Userinfo" xmlns:xsd="http://www.w3.org/1999/XMLSchema"> <import location="http://localhost:8080/wsdl/Userinfo_Service-interface.wsdl" namespace= "http://www.userinfoservice.com/Userinfo-interface"> </import> <service name="Userinfo_Service"> <documentation>} IBM WSTK 2.0 generated service definition file </documentation> <port binding="Userinfo_ServiceBinding" name="Userinfo_ServicePort"> <soap:address location="http://localhost:8080/soap/servlet/rpcrouter"/> </port> </service> </definitions>
こうすることによって、同じインターフェイスを持つサービスを複数のサイトから提供するような記述が可能である。
WSDLはいつ必要になるかというと、いままで接続したことのないソフトウェアが、このサービスに初めてアクセスしてくるときに必要になる。そんなことホントにあるのか? と思われる方もおられるだろう。ごもっともである。しかし、これはコンポーネントソフトウェアに必須の機能である。
例えばJavaBeansのリフレクションやイントロスペクションの機能は、JavaBeansが持つフィールド、メソッドなどの情報を取得するための機能である。これは、JavaBeansに準拠したソフトウェアコンポーネントに登録(アドイン)するときに必須の機能である。
同様に、ある機能を提供するWebサービスをコンポーネントと見て、システムに登録するときに、これと同様のことが必要である。それを実現するのがWSDLであると考えればよい。アドインされた後、接続先を探すのはUDDIの役目である。以下のようなストーリーが考えられるだろう。
■Webサービスをコンポーネントとして扱うプログラミング
ある開発環境において、コンポーネント部品を組み合わせてシステムを構築するとき、WSDLを登録すると、そのWebサービスを1つのコンポーネントとして扱うことができる。実際に接続するときに使われるようなクライアントソフトウェア部品は、自動生成できるはずだ。
■ゲートウェイ製品が動的にアクセス
あるデータ項目やXMLのボキャブラリを交換することが分かっているデータ交換において、いままでそのゲートウェイが経験したことのないインターフェイス定義を通過しなければならないとき、WSDLを見て、動的に接続することが可能になるかもしれない。データ項目やセマンティクスが事前に分かっているなら可能なはずである。
■仕様変更に柔軟なクライアントを開発する
IBM Web Services Toolkit(WSTK)のJava-APIでは、ServiceProxyというSOAPサービスにアクセスするためのプロキシクラスをWSDLを入力にして動的に生成する機能が提供されている。ファクトリー機能である。こういった機能を利用することで、クライアントソフトウェアがWSDLの特定のバージョンに依存せずに作ることができるようになる。入力になるデータ項目が、目的のWSDLに必要なだけそろっていれば、サーバのバージョンアップなどのときにWSDLが変化しても、アクセスするプログラムコードは、修正・コンパイルは必要ない。これは、ゲートウェイ製品にも重要なことである。
■UDDIとの連携
Webをインフラとして使い、XMLベースのデータ交換を行うときに発生するさまざまな課題を解決するためのプロトコルのベースになるSOAPが存在すること、「Webサービス」を登録し、動的に検索するための基盤であるUDDIが存在すること、などを説明してきた。そして、WSDLがインターフェイスを定義できる。これらは組み合わせて使うことによって、大きな威力を発揮する。Webサービスのインターフェイスの種類をUDDIに登録するのは、tModelという要素であり、その説明自体はそこに記述されず、外に定義した「何か」であり、URLによって定義することになっている。
WSDLは、インターフェイスを定義するためのXMLフォーマットであるので、tModelに登録することができる。UDDIに登録することによって、どのようなことができるようになるかを説明してみよう。
WSDLはだれが定義するのだろうか。WSDLを定義する(インターフェイスを定義する)人は、その状況によってさまざまなことが考えられるだろう。しかし、1つの答えとして「ソフトウェアを提供する企業」ということが考えられる。今日、クライアント/サーバ型のプログラムは非常に多い。特にサーバ製品の管理用GUIなどはほとんどクライアント/サーバ型である。このサーバが提供するインターフェイスは、GUIを使う人が決めるわけではないし、多くの場合業界標準ではない。そのサーバ製品を作ったソフトウェアベンダが独自に提供するインターフェイスである。
Webサービスでも同様のことが考えられるだろう。あるサーバ・ソフトウェアを、例えばSOAP-RPCベースのインターフェイスで作ったとき、そのインターフェイスを考えるのはそのサーバ・ソフトウェアを作った企業であり、WSDLを定義するとすればその企業の人間である。また、既存のXML仕様は、多くの団体が規定しており、その中には、DTDなどで規定されるスキーマだけでなく、メッセージや交換順序といったプロトコルに近いものを定義しているものもある。これらは、WSDLである程度表現することが可能なはずだ。そういったWSDLを作るのは、それらを規定している団体かもしれない。こういった定義が必要なのは、インターフェイス定義だけであるので、前の例にあるように、type、message、portType、bindingのみでよいはずだ(service要素、port要素にあたる情報は、UDDI上のbusinessService要素やbindingTemplate要素で提供する)。
規定されたWSDLをUDDIで利用するには、UDDI上にtModelとして定義(登録)される必要がある。登録するには、それぞれの企業、または団体が、自身のHTTPサイトにWSDLファイルを置き、そのURLをUDDIのtModelに指定すればよい。
UDDIに登録されたWSDLのインターフェイスに準拠したWebサービスを提供する企業は、そのソフトウェアを準備する必要がある。ソフトウェアベンダが提供しているWSDLであれば、そのパッケージソフト(のサーバ機能)を購入してサーバを構築することもあるだろう。団体が定義したWSDLを利用するのであれば、その団体に参加して、ソフトウェアを独自開発するのかもしれない。そして、「うちは、このインターフェイスでWebサービスを提供しています」という内容のbusinessSevice情報(イエローページおよびグリーンページ)をUDDIに登録することになる。
ソフトウェアベンダが提供するクライアントソフトが、UDDI上でtModelに登録された接続相手を探すとき、WSDLはあまり必要ない。UDDI上のtModelのtMdeolKey(uuid)がクライアントソフトウェアから認識されていれば、それを探して接続すればよいのである。WSDLのURLから、tModelを検索するということもあるかもしれない。
接続するソフトウェアは、UDDIを使って検索し、tModel要素からWSDLを参照する。接続するときに、動的にWSDLを参照して、接続相手との相性を確認したり、動的にプロキシクラスを生成するなどによって、柔軟な接続を実現する。
以上、WSDLによってXMLデータ交換にもたらされる可能性などを解説した。次回は、いよいよ、SOAP、UDDI、WSDLに対応したアプリケーション・サーバとツールキットなどを使って、具体的にWebサービスを構築する手順などを解説する。
Copyright © ITmedia, Inc. All Rights Reserved.