まずは、Webサービスの内容やインターフェイスを取得するところから始める。そのためのWSDLがサーバから公開されているので、Webブラウザで、次のURLをアクセスしてみよう。
http://hostname/wsdl/WstkTest_Service.wsdl http://hostname/wsdl/WstkTest_Service-interface.wsdl
これを利用して、サービスにアクセスするためのプロキシを生成し、Webサービスにアクセスしてみる。
プロキシを生成するには、proxygen.batを使う。これはGUIのツールではないので、コマンドプロンプトで、以下のコマンドを実行する。
C:\_work\wstk\bin>proxygen http://hostname/wsdl/WstkTest_Service.wsd >> Importing http://localhost/wsdl/WstkTest_Service-interface.wsdl . >> Transforming WSDL to NASSL .. >> Generating proxy .. Created file C:\_work\wstk\bin\WstkTest_ServiceProxy.java Compiled file C:\_work\wstk\bin\WstkTest_ServiceProxy.java Done.
これによって、プロキシクラスが生成される。プロキシクラスを生成することによって、簡単にWebサービスにアクセスできる。Webサービスにアクセスするためのコードは、以下のようになる。
public class TestGetSystemProperty { public static void main(String[] args) throws Exception { WstkTest_ServiceProxy wt = new WstkTest_ServiceProxy(); String key = "java.vm.vendor"; if(args.length > 0) key = args[0]; System.out.println(key + "=" + wt.getSystemProperty(key)); } }
お気付きの方も多いかと思うが、元のクラスファイルが持っているテスト用のmainメソッドとほぼ同じ内容である。違うのは、newしているのが、WstkTest_ServiceProxy()である点だ。このプログラムは実行すると、元のクラスファイルと同じ動作をするのはいうまでもない。しかも、サーバとは別のマシンで実行可能である。システム・プロパティは、サーバのものが表示される。
次に、UDDIを利用してサービスを名前で検索して発見し、利用するというロジックを記述してみよう。同じ名前のサービスを複数のサーバで提供すれば、すべてを呼び出すことも可能である。サービスの名前は、サービス記述WSDLの<definitions>要素のname属性で指定されているものである。
<definitions name="WstkTest_Service">
このサービスは、WstkTest_Serviceと名付けられていることが分かる(これは、パブリッシュのときに自分で変えてもよい)。
UDDI4JのAPIを使ってこれらを事細かに探していけばSOAPへのアクセスもできるが、Web ServicesアーキテクチャではUDDIのタグをどのように使うかをルール付けし、それにアクセスするためのAPIを別途準備している。それがWSTK-APIであり、com.ibm.wstk以下のパッケージに含まれている。次のソースコードは、WSTK-APIを使ってUDDIを検索し、SOAP-RPCにアクセスする非常に単純な例である。
import org.apache.soap.encoding.SOAPMappingRegistry; import org.apache.soap.rpc.Response; import org.apache.soap.Constants; import com.ibm.wstk.service.registry.*; import com.ibm.wstk.service.definition.*; import com.ibm.wstk.service.client.*; import com.ibm.wsdl.*; public class TestGetSystemProperty2 { public static void main(String[] args) throws Exception { String service= "WstkTest_Service"; String port= "WstkTest_ServicePort"; String operation= "getSystemProperty"; // サービス・レジストリ(UDDI)へアクセス ServiceRegistryProxy srp = new ServiceRegistryProxy( new URL("http://hostname:8080/services/uddi/servlet/uddi") ); // サービスを検索 ServiceDefinition[] sdList = srp.findServices(service, false); // 一覧の最初の1つを使う ServiceDefinition sd = sdList[0]; // WSDLドキュメントを取得 WSDLDocument wsdl = sd.getServiceImplementation().getWSDLDocument(); // プロキシ・オブジェクトを動的に生成 ServiceProxy proxy = ServiceProxyFactory.getServiceProxy(service, port, wsdl); // サービスの呼び出し Response res = proxy.invoke(operation, args,Constants.NS_URI_SOAP_ENC); // 戻り値の取り出し Object ret = res.getReturnValue().getValue(); // 表示 System.out.println("Result="+ret); } }
このプログラムはいきなり実行すればよい。プロキシの生成という手順は必要ない。
このプログラムでは、UDDIレジストリーに「WstkTest_Service」という名前のサービスを見つけ出し、その中の「WstkTest_ServicePort」というポートを見つける(今回のサンプルでは、SOAP-RPC over HTTPのサービスポートである)。 そのポートの中にはgetSystemPropertyというメソッド(operation)があるはずなので、それを呼び出す。引数はargs(mainメソッドの引数)がそのまま渡される。
このコードの特徴的な部分は、WSDLやWebサービスの具体的なものを何一つプログラムコードにハードコードしていない点にある(変数のservice、port、operationなどはストリングなので、外からでも与えられるため、ハードコードしているとはいえない)。WSDLを動的に参照し、渡されたポートを探してメッセージタイプを認識し、動的にSOAP-RPC形式のXML文書を生成して送信する。返信されてきたドキュメントも中身は分かっているので、それを適宜分解(あるときにはオブジェクト化)して、レスポンスとして取り出すことができる。
つまり、プログラムの入力として「アクセスしたいサービス名」「ポートの種類」「メソッド(operation)」「引数」などをすべて渡すだけで、WSDLを持つほかのWebサービスにもアクセスできるコードとして稼働できるのである。これを「ダイナミック・バインディング」と呼んでいる。
C:\_work\wstk\bin>java TestGetSystemProperty2 java.vm.vendorReusult=IBM Corporation
このような機能は、BSF(Bean Scripting Framework)のようなスクリプティング言語からアクセスする場合には重要だ。また、Javaではない別の言語体系からWebサービスにアクセスするときには、このような処理が常に行われることになるだろう。JavaBeansでは、コンポーネントとして扱うときに、自己記述機能としてリフレクションやイントロスペクションという機能を提供している。ここで紹介した機能も、同じようにWebサービスをWebライブ・コンポーネントとして扱うときに必要な、自己記述機能として働くことになるだろう。
SOAP、セキュリティ、UDDI、WSDL、ツールキットと連載を続けてきた。Webサービスが、eビジネスを次世代のものに進化させ、ダイナミックなeビジネスを実現するための基盤を提供することをご理解いただけただろうか。これらのテクノロジは革新的ではないが、インターネットを確実に進化させる。そして、その結果、ビジネス・モデルが大きく変わるほどの力を持っていると筆者は感じている。
次回は、連載の最終回として、最新のWebサービス記述の標準を目指す Web Service Flow Language(WSFL)を概説する。
Copyright © ITmedia, Inc. All Rights Reserved.