サービスの実装
HelloIF.javaを再掲します。
package helloservice; import java.rmi.Remote; import java.rmi.RemoteException; public interface HelloIF extends Remote { public String sayHello(String s) throws RemoteException; }
java.rmi.Remoteインターフェイスを継承して、サービスのインターフェイスを定義します。
ここでは、Stringを受けてStringを返すsayHelloメソッドを定義しています。
サービスとして公開するすべてのメソッドに throws java.rmi.RemoteExceptionをつけなければいけません。
続いて、HelloImpl.javaも再掲します。
package helloservice; public class HelloImpl implements HelloIF { public String message ="Hello"; public String sayHello(String s) { return message + s; } }
普通にHelloIFをimplementします。...と、ここまではRMIでの方法と何も変わりませんね。これまでRMIで実装してきた機能を簡単にWebServiceにできるようにという心遣いでしょうか。
で、この実装を持つサービスをWebServiceとして公開する手順が、サンプルのAntスクリプトに書かれています。各タスクは、実際にはcommon\targets.xmlに書かれています。
まずはcompile-serviceタスク。ここではbuild用のディレクトリを掘ってjavacでコンパイルしているだけです。
次にgenerate-sei-serviceタスク。このタスクでは、サービスを表すデータをmodel.gzファイルに書き出します。
model.gzについては「internal data structure」とありますから、ツール用のデータなのでしょう。中をのぞいてみましたが意味不明のXMLでした。
このとき、config-interface.xmlファイルが必要になります。このファイルでは、以下の指定をします。
- サービスの名前はMyHelloService
- WSDLの名前空間はurn:Foo
- MyHelloServiceのクラス郡のパッケージはhelloservice
- サービスのインターフェイス(サービス・エンドポイント・インターフェイス)はhelloservice.HelloIF
以下のようなXMLファイルになります。
<?xml version="1.0" encoding="UTF-8"?> <configuration xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/config"> <service name="MyHelloService" targetNamespace="urn:Foo" typeNamespace="urn:Foo" packageName="helloservice"> <interface name="helloservice.HelloIF"/> </service> </configuration>
ちなみに、Webサービスの機能を提供するプログラムコードのことを「サービス・エンドポイント」と呼ぶそうです。エンドポイントの機能は、interface句で定義されることになっており、これを「サービス・エンドポイント・インターフェイス(SEI)」と呼ぶのだそうです。(上でリンクを張った@ITの記事より)
続いてpackage-serviceタスク。ここでは、distディレクトリを掘ってhello-jaxrpc-portable.warファイルを作成します。このwarファイルは、まだ配備できるものではありません。サーバ側でJAX-RPCランタイムとHelloImplクラスの間を取り持つtieクラスができていないからです。
hello-jaxrpc-portable.warファイルには以下のファイルが含まれます。
- WEB-INF/classes/hello/HelloIF.class
- WEB-INF/classes/hello/HelloImpl.class
- WEB-INF/jaxrpc-ri.xml
- WEB-INF/model.gz
- WEB-INF/web.xml
jaxrpc-ri.xmlは、JAX-RPCの仕様ではなく、JWSDPの実装特有のものです。一方、web.xmlは仕様で定められたものです。
jaxrpc-ri.xmlには、以下のように記述します。(これも再掲)
<?xml version="1.0" encoding="UTF-8"?> <webServices xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/dd" version="1.0" targetNamespaceBase="urn:Foo" typeNamespaceBase="urn:Foo" urlPatternBase="/ws"> <endpoint name="MyHello" displayName="HelloWorld Service" description="A simple web service" interface="helloservice.HelloIF" model="/WEB-INF/model.gz" implementation="hello.HelloImpl"/> <endpointMapping endpointName="MyHello" urlPattern="/hello"/> </webServices>
webServices要素のurlPatternBase属性は、正直なぜ/wsと書くのかわかりません。
endpoint要素のdisplayNameやdescriptionはコメントだと思います。他は大体わかりますね。
endpointMapping要素のurlPattern属性は、サービスが公開されるurlの一部になります。
web.xmlをも再掲。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/j2ee/dtds/web-app_2_3.dtd"> <web-app> <display-name>Hello World Application <description>A web application containing a simple JAX-RPC endpoint <session-config> <session-timeout>60 </session-config> </web-app>
意味のありそうなのは、session-timeoutだけでしょうか。間違ってたらコメントで指摘してください。
次にprocess-warタスク。ここまで来てようやく、配備可能なwarファイルができます。hello-jaxrpc-portable.warファイルを読み込んで、hello-jaxrpc.warファイルを吐き出します。
このhello-jaxrpc.warファイルの中身はこうなっています。
- META-INF/MANIFEST.MF
- WEB-INF/jaxrpc-ri-before.xml
- WEB-INF/jaxrpc-ri-runtime.xml
- WEB-INF/model.gz
- WEB-INF/MyHelloService.wsdl
- WEB-INF/web-before.xml
- WEB-INF/web.xml
- WEB-INF/classes/helloservice
- WEB-INF/classes/HelloIF.class
- WEB-INF/classes/HelloIF_sayHello_RequestStruct.class
- WEB-INF/classes/HelloIF_sayHello_RequestStruct__MyHello__SOAPBuilder.class
- WEB-INF/classes/HelloIF_sayHello_RequestStruct__MyHello__SOAPSerializer.class
- WEB-INF/classes/HelloIF_sayHello_ResponseStruct.class
- WEB-INF/classes/HelloIF_sayHello_ResponseStruct__MyHello__SOAPBuilder.class
- WEB-INF/classes/HelloIF_sayHello_ResponseStruct__MyHello__SOAPSerializer.class
- WEB-INF/classes/HelloIF_Tie.class
- WEB-INF/classes/HelloImpl.class
- WEB-INF/classes/MyHelloService_SerializerRegistry.class
このwarファイルを手動でwebappsディレクトリにおいてTomcatのmanagerアプリケーションでデプロイしても、deployタスクでデプロイしてもOKです。
ここまでの内容を整理すると、作成するのは
- サービスのエンドポイント・インターフェイス(Java interface)
- サービスの実装クラス(Java class)
- サービスおよびエンドポイント・インターフェイスについて記述するconfig-interface.xml
- サービスおよびエンドポイント・インターフェイスの配備場所について記述するjaxrpc-ri.xml
- webサーバの設定を記述するweb.xml
ということになります。