EJB 3.0 ベースの Web サービス

Table of Contents

EJB 3.0 ベースの Web サービス

チュートリアルWebサービスと、それが現在のコンピューティングの世界でどれほど注目を集めているか、ご存知でしょう。しかし、少なくともJavaにおいては、JavaベースのWebサービスを実装する方法は数多く存在します。SunのJava WebサービスツールキットやApache Axisツールキット、あるいはアプリケーションサーバー独自の機能(WebSphereが提供するものなど)を使うこともできます。もちろん、独自に開発することも可能です。

私自身の場合、これらの選択肢と、基盤となる操作の複雑さに直面した結果、Axisを使うことにしました。AxisはJavaでのWebサービス作成を大幅に簡素化します。プログラマーはXML、SOAP、JAX-RPC、JAXP、WSDLといった低レベルの詳細に煩わされることなく、JavaベースのWebサービスとWebサービスクライアントを簡単に作成でき、他のJavaフレームワークを使用する場合とほとんど変わりません。

ただし、Axis は言語の標準的な部分ではありません (それ自体はほぼ事実上の標準ですが)。

Java EE 5.0では、Javaクラスにアノテーションを付けるだけでWebサービスを作成できる、使いやすいメカニズムがJavaに組み込まれました。本コラムでは、Java SE 5.0で導入された標準Javaアノテーション、EJB 3.0クラス、そしてEJB 3.0準拠のアプリケーションサーバーを用いてWebサービスを作成する方法について解説します。[注: 厳密に言えば、JBoss 4.0.5はEJB 3.0に完全準拠しているわけではありませんが、ほぼ準拠しています。]

EJB 3.0仕様

エンタープライズJavaBeans(EJB)のEJB 3.0仕様には、EJB仕様の完全な改訂が組み込まれています。この改訂は、EJBの実装と保守を大幅に簡素化することを目的としています。やや複雑なリモートインターフェース、実装クラス、ホームインターフェース、XMLデプロイメント記述子などは不要になりました。

代わりに、Javaアノテーションは、Javaクラスを適切にコンパイルおよびデプロイするために使用できる特定のプロパティをクラスにマークするために使用されます。したがって、@StatelessアノテーションがマークされたJavaクラスはステートレスEJBと呼ばれます。その他のオプションには@Stateful、、、@MessageDrivenなどがあります@Entity。EJB 3.0ベースのWebサービスは、これに基づいて構築されており、追加のアノテーションを組み込むことで、EJBがWebサービスの実装を提供していること、およびそのWebサービスで利用可能なプロトコルをマークすることができます。このコラムの後半では、単純なEcho Webサービスを例に挙げて、この例を見ていきます。

Web サービスとは何ですか?

EJB 3.0 ベースの Web サービスの実装方法を検討する前に、まず Web サービスとは何かを考えてみましょう。Web サービスとは、(現時点では)HTTP プロトコルと XML データ形式を使用して、異機種ネットワーク上で実行される分散アプリケーションに他なりません。もちろんこれは大げさな表現ですが、中核となる概念を示しています。つまり、Web サービス クライアントを 1 台のマシンに(任意の言語で)実装し、その後、インターネット上のどこかにあるホスト マシン上の「サービス」を呼び出すことができます。プラットフォーム、実装言語、またはサービスのベンダーを気にする必要はありません。クライアントとホストされているサービスの実装間の呼び出し方法は、HTTP で転送される XML であるため、プロセス全体が言語とプラットフォームに依存しません。

Webサービスの「標準化」を支援するために、様々な技術が登場しています。これらの技術はベンダーや言語に依存しておらず、以下のようなものがあります。

  • 石鹸
  • 添付ファイル付き SOAP (または SwA)
  • WSDL
  • UDDI

ここで鍵となる技術はSOAPです。SOAPはかつてSimple Object Access Protocolの略称でしたが、現在ではW3Cによって誤解を招くとされています。SOAPには、SOAPメッセージのリモートプロシージャコールとレスポンスを表現するSOAP RPCが含まれています。

もう一つの重要な技術はWSDLです。WSDL(Web Services Description Language)は、Webサービスインターフェースを記述するためのXMLボキャブラリです。具体的には、以下の要素を定義します。

  • サービス
  • サーバー上の操作のセット
  • クライアント呼び出しの形式
  • Javaインターフェースに少し似ていますが、言語に依存しません。

つまり、WSDLはクライアントから送信されるSOAPメッセージの内容がどのようなものであるべきかを記述します。また、クライアントに返されるSOAPメッセージがどのようになるかも記述します。

EJB 3.0 ベースの Web サービスと JBoss などのアプリケーション サーバーを使用する場合、SOAP や WSDL のほとんどは隠れているため、あまり心配する必要はありません。

EJB3 Webサービスの実装

アプリケーションサービス

EJB3ベースのWebサービスをデプロイしてテストするには、EJB3準拠のアプリケーションサーバーが必要です。このコラムでは、JBossアプリケーションサーバー、特にJBossバージョン4.0.5(以下に示すコードはこのバージョンでテスト済み)を使用します。このバージョンのJBossはそのまま使用するため、コアリリース以外は何もインストールする必要はありません。コアリリースはJBossのこちらのサイトからダウンロードできます。SunのEJB3ダウンロードサイトはこちらです。また、EJB 3.0チュートリアル(およびSun Java EE 5のチュートリアル)、そしてSun EJB 3.0 FAQも参考になるかもしれません。

Webサービスビジネスインターフェース

EJB3ベースのWebサーバーを作成するには、まずリモートインターフェース(サービスエンドポイントインターフェース)を定義します。このインターフェースは、Webサービスが公開するメソッドを指定します。今回は非常にシンプルに、echoメソッド1つを持つインターフェースを定義します。このメソッドは文字列を受け取り、その文字列にウェルカムメッセージを追加して結果を返します。このインターフェースは と呼ばれEcho、以下のリストに示されています。

パッケージ com.theregister.webservice; インポート java.rmi.Remote; インポート javax.jws.WebMethod;
javax.jws.WebService をインポートします。
javax.jws.soap.SOAPBinding をインポートします。
javax.jws.soap.SOAPBinding.Style をインポートします。@WebService
@SOAPBinding(スタイル = Style.RPC)
パブリック インターフェイス Echo は Remote を拡張します { String echo(String e);
}

このインターフェースにはいくつか注意すべき点があります。まず、このインターフェースがWebサービスを定義し、メソッド echo がWebメソッドであることを指定するためにアノテーションを使用している点です。これは@WebServiceインターフェースのアノテーションによって行われます。このアノテーションはJava Web Services ()パッケージの一部ですjavax.jws。この@WebServiceアノテーションは、クラスがWebサービスを実装していること、またはインターフェースがWebサービスインターフェースを定義していることを識別します。

このインターフェースの2番目のアノテーションは、パッケージSOAPBindingからのアノテーションですjavax.jws.soap。このアノテーションは、WebサービスとSOAPメッセージプロトコルのマッピングを定義します。このアノテーションのスタイル要素は、Webサービスとの間で送受信されるメッセージのエンコード方式を指定できます。有効な値はDocumentとRPCです。この例では、よりシンプルなサービスエンドポイントインターフェースを実現できるRPCを使用しています。

Webサービス実装クラス

Webサービスのリモートインターフェースを定義したので、実装クラスを定義できます。ステートレスセッションBeanとして実装するため、このクラスを と名付けますEchoBean。このクラスの機能はEchoBean、渡される文字列の先頭に「Web Service Echo +」という文字列を追加することです。EchoBeanクラスを以下に示します。

パッケージ com.theregister.webservice; インポート javax.ejb.Remote;
javax.ejb.Stateless をインポートします。
javax.jws.WebService をインポートします。@Stateless
@WebService(エンドポイントインターフェース = "com.theregister.webservice.Echo")
@Remote(Echo.クラス)
パブリッククラスEchoBean { パブリックString echo(String e) { return "Web Service Echo + " + e; }
}

ここでも、アノテーションを使用してこのクラスの意味を定義します。つまり、 を使用して、@Stateless annotationこれがステートレス セッション Bean であることを示します。このアノテーションは パッケージの標準部分ですjavax.ejb。また、この場合、@Remoteアノテーションを使用して、このクラスのリモート ビジネス インターフェースを定義します。これらのアノテーションは両方とも、標準の EJB3 ステートレス セッション Bean を定義するために使用できます。3 つ目のアノテーションである アノテーションは、@WebServiceこの Bean が Web サービスの実装も提供することを宣言するために使用されます。この場合、 WebService アノテーションにはendpointInterface要素が含まれています。この要素はインターフェース上で定義できません。これは、Web サービスの WSDL 要素を作成するために使用される定義を見つけるために、アプリケーション サーバーが参照する場所を指定するために使用されます。この場合、これは EchoBean クラスがリモート インターフェースとして実装するインターフェースでもありますが、必ずしもそうであるとは限りません。これで、ステートレス セッション EJB の Web サービスを作成するのに必要な作業がすべて完了しました。これで、これら 2 つのクラスをコンパイルし、jar ファイルにパッケージ化できます。このjarファイルは、これら2つのクラスのみを含むシンプルなjarファイルです。追加のXMLファイルは必要ありません。作成したjarファイルは ですecho.jar

JBossへのデプロイ

このEJBベースのWebサービスをJBossにデプロイするには、JBossサーバーのデプロイディレクトリにコピーするだけです。私の場合、JBossサーバーの名前は「default」なので、以下の場所にコピーする必要があります。

C:\jboss-4.0.5.GA\server\default\deploy

JBossを起動し、jarファイルをdeployディレクトリにコピーすると、自動的にデプロイされます。成功すると、JBossの出力コンソールに次のメッセージが表示されます。

19:05:06,750 INFO [サーバー] JBoss (MX MicroKernel) [4.0.5.GA (ビルド: CVSTag=Branch_4_0 日付=200610162339)] 50秒204ミリ秒で起動しました

19:05:53,953 INFO [Ejb3Deployment] EJB3のデプロイメントにかかった時間: 1219

19:06:00,125 INFO [TomcatDeployer] デプロイ、ctxPath=/echo、warUrl=.../tmp/deploy/echo.jar-ws2206.war/

19:06:01,593 INFO [JmxKernelAbstraction] MBeanをインストールしています: jboss.j2ee:jar=echo.jar,name=EchoBean,service=EJB3 依存関係あり:

19:06:02,359 INFO [EJBContainer] EJB が開始されました: com.theregister.webservice.EchoBean ejbName: EchoBean

19:06:08,421 INFO [EJB3Deployer] デプロイ済み: ファイル:/C:/jboss-4.0.5.GA/server/default/deploy/echo.jar

19:06:08,468 INFO [WSDLFilePublisher] WSDLが次の場所に公開されました: file:/C:/jboss-4.0.5.GA/server/default/data/wsdl/echo.jar/EchoService2205.wsdl

19:06:08,500 INFO [ServiceEndpointManager] WebService が開始されました: http://HAL:8080/echo/EchoBean

上記からわかるように、JBossはデプロイすべき新しいEJB3セッションBeanがあることを認識し、それをデプロイしました。その後、Webサービス用のWSDLファイルを生成し、URL からアクセスできるWebサービスを開始しましたhttp://HAL:8080/echo/EchoBean。この自動生成されたWSDLファイルは、?wsdlこのURLに「 」を追加することで表示できます。つまり、次のURL からWSDLファイルにアクセスできますhttp://HAL:8080/echo/EchoBean?wsdl。実際に生成されたファイルは、Firefoxで図1に示されています。

JBossから生成されたコードを表示します

これで、Echo Web サービスにアクセスするクライアントを実装できるようになりました。

Webサービスクライアント

ウェブサービスに文字列を送信し、ウェブサービスから返された文字列を出力することのみを目的とした、非常にシンプルなクライアントを実装します。このシンプルなウェブサービスクライアントクラスは以下のとおりです。

パッケージ com.theregister.client; java.net.URL をインポート; javax.xml.namespace.QName をインポート;
javax.xml.rpc.Service をインポートします。
import javax.xml.rpc.ServiceFactory; import com.theregister.webservice.Echo; public class Client { public static void main(String[] args) throws Exception { System.out.println("テスト クライアントを開始しています"); URL url = new URL("http://HAL:8080/echo/EchoBean?wsdl"); QName qname = new QName( "http://webservice.theregister.com/jaws", "EchoService"); System.out.println("次のサービスを作成しています: \n\t" + url + " \n\tand " + qname); ServiceFactory factory = ServiceFactory.newInstance(); Service remote = factory.createService(url, qname); System.out.println("プロキシ オブジェクトへの参照を取得しています"); Echo proxy = (Echo) remote.getPort(Echo.class); System.out.println("ローカル プロキシにアクセスしました: " + proxy);文字列 string = "John"; System.out.println("送信中: " + string); System.out.println("受信中: " + proxy.echo("John")); }
}

リストに示されているように、Webサービスクライアントクラスには、テストハーネスとして使用されるpublic static void mainメソッドが1つ含まれています。このメソッドには複数のデバッグ出力が含まれており、動作を容易に追跡できます。このクラスの重要な機能は次のとおりです。

  1. USDL ファイルを参照する URL オブジェクトを作成します。
  2. サービス ファクトリで使用される QName (修飾名) オブジェクトを作成します。
  3. ServiceFactory オブジェクトを使用して、指定された QName のリモートサービスを取得します。サービスオブジェクトの目的は、クライアントがリモート Web サービスへの参照を取得できるようにすることです。
  4. リモートWebサービスへの「参照」は、Webサービスのリモートビジネスインターフェースを実装したローカルプロキシの形で提供されます。このプロキシオブジェクトは、Webサービスに送信されるパラメータの整列化、SOAP/HTTP経由でのWebサービスへのデータ転送、そしてWebサービスから返される結果の逆整列化に必要なすべての機能を提供します(これにより、Webサービスへのアクセスが大幅に簡素化されます)。
  5. 次に、プロキシ オブジェクトで echo メソッドが呼び出され、結果の文字列が出力されます。

上記の手順で最も興味深い点は、 の使用ServiceFactoryと、結果として得られる Service オブジェクトの使用です。ServiceFactory インスタンスは、自動生成された WSDL ファイルの URL と、アクセスされる実際のサービスの修飾名という 2 つのパラメータを取ります。 はServiceFactoryWSDL ファイルにアクセスし、EchoService指定されたターゲット名前空間内の に関する情報を取得します (この場合、WSDL ファイルには に関する情報のみが含まれますEchoBeanが、他の Web サービスに関する情報も含まれる可能性があります)。 Web サービスにアクセスしたら、適切な「ポート」にアクセスして、結果を Echo インターフェイスにキャストするだけです。つまり、サービス エンドポイント インターフェイス (または返されることが予想されるオブジェクトのタイプ) を指定する必要があり、サービス オブジェクトは適切な動的プロキシを生成しようとします。したがって、この場合は、Echo インターフェイスを実装するものが必要であり、それが何を返すかを表します。

クライアントの実行

クライアントを実行するには、クラスパス上に適切なjarファイルが配置されていることを確認する必要があります。これは一見簡単そうに思えますが、実際にはそうではありません。適切なWebサービスjarファイルだけでなく、基盤となるSOAP、XML、XML RPC jarファイルにもアクセスできる必要があるからです。そこで、Windowsマシン上でこのシンプルなクライアントを実行するには、以下のスクリプトを使用します。

rem @echo オフ
JBOSS_HOME=C:\jboss-4.0.5.GA を設定し、CLASSPATH=..\build\classes を設定します。
CLASSPATH=%CLASSPATH%;%JBOSS_HOME%\client\jboss-saaj.jar を設定します。
CLASSPATH=%CLASSPATH%;%JBOSS_HOME%\client\jboss-ejb3-client.jar を設定します。
CLASSPATH=%CLASSPATH%;%JBOSS_HOME%\client\jboss-xml-binding.jar を設定します。
CLASSPATH=%CLASSPATH%;%JBOSS_HOME%\client\jboss-jaxrpc.jar を設定します。
CLASSPATH=%CLASSPATH%;%JBOSS_HOME%\client\jbossws-client.jar を設定します。
CLASSPATH=%CLASSPATH%;%JBOSS_HOME%\client\activation.jar を設定します。
CLASSPATH=%CLASSPATH%;%JBOSS_HOME%\client\mail.jar を設定します。
CLASSPATH=%CLASSPATH%;%JBOSS_HOME%\client\wsdl4j.jar を設定します。
CLASSPATH=%CLASSPATH%;%JBOSS_HOME%\lib\endorsed\xercesImpl.jar を設定します。
CLASSPATH=%CLASSPATH%;%JBOSS_HOME%\client\jbossall-client.jar を設定します。
CLASSPATH=%CLASSPATH%;%JBOSS_HOME%\server\default\lib\jboss-remoting.jar を設定します。java -cp %CLASSPATH% com.theregister.client.Client

この例ではJBossを使用しているため、使用するjarファイルはJBossのバージョンであることに注意してください。異なるEJBアプリケーションサーバーを使用している場合は、クラスパスを適切に変更する必要があります。

クライアントの実行結果を以下に示します。

テストクライアントの起動
http://HAL:8080/echo/EchoBean?wsdl および {http://webservice.theregister.com/jaws}EchoService を使用してサービスを作成します。
プロキシオブジェクトへの参照を取得する
アクセスしたローカルプロキシ: org.jboss.ws.jaxrpc.CallImpl@f39b3a
送信者: ジョン
受信: Web サービス Echo + John

まとめ

このコラムからわかるように、EJB3ベースのWebサービスの実装とデプロイは非常に簡単で、従来のJava Webサービスツールキットよりもはるかにシンプルです。私自身、次にWebサービスプロジェクトを立ち上げる際には、Axis 2ツールキットに加えてEJB3も検討するつもりです。

Discover More