サービスの実装

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ファイルが必要になります。このファイルでは、以下の指定をします。

以下のような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です。

ここまでの内容を整理すると、作成するのは

ということになります。