Oracle® Fusion Middleware Oracle WebLogic Server JAX-RPC を使用した Web サービスの高度な機能のプログラミング 11g リリース 1 (10.3.1) B55544-01 |
|
![]() 戻る |
![]() 次へ |
以下の節では、会話形式の Web サービスの作成方法について説明します。
Web サービスと、その Web サービスが呼び出すクライアント アプリケーションは、1 つのタスクを完了するために複数回通信する場合があります。また、複数のクライアント アプリケーションが同時に同じ Web サービスと通信する場合もあります。会話を使用すると、直接的な方法で、呼び出し間のデータを追跡して、Web サービスが常に正しいクライアントに応答するようにできます。
会話を使用すると、複数の通信にわたってデータを維持することに伴う以下の 2 つの問題が解決されます。
会話では、1 つのクライアント アプリケーションと 1 つの Web サービス間の双方向通信がユニークに識別されるので、メッセージが常に正しいクライアントに返される。たとえば、ショッピング カート アプリケーションでは、どのショッピング カートがどの顧客に属するかを会話形式の Web サービスが追跡します。会話形式の Web サービスでは、クライアント アプリケーションとの間で新しい会話が始まるたびに、ユニークな会話 ID を作成することによって、これを実装しています。
会話によって Web サービスへの呼び出し間のステートを保持する。つまり、サービスに対する呼び出し間の特定のクライアント アプリケーションに関連付けられているデータを追跡します。会話を使用すると、特定のクライアントに関連付けられているデータは、必要がなくなるまで、または処理が完了するまで、確実に保存されます。たとえば、ショッピング カート アプリケーションでは、顧客がショッピングを続けている間、ショッピング カートに入っている品物を会話形式の Web サービスが記憶します。ステートの保持はまた、会話の最中に Web サービスをホストするコンピュータで発生した障害に対処するためにも必要です。すべてのステート関連データがディスクに永続化されるので、コンピュータが再起動すれば、クライアント アプリケーションとの会話を続行できます。
WebLogic Server はこのユニークな ID とステートを、クライアント アプリケーションが新しく会話を開始するたびに会話コンテキストを作成することによって管理します。Web サービスがその後、このコンテキストを使用して、サービスとの間の呼び出しを相関させ、ステート関連データを永続化します。
クライアント アプリケーションと Web サービスの間の会話には、明確なフェーズが 3 つあります。
開始 - クライアント アプリケーションが、会話形式の Web サービスの開始オペレーションを呼び出すことによって、会話を開始します。次にその Web サービスが、新しい会話コンテキストおよびそれに伴うユニークな ID を作成し、アイドル時間と会話の存続期間を計測する内部タイマーを起動します。
続行 - クライアント アプリケーションは会話を開始した後、1 つまたは複数の続行オペレーションを呼び出して会話を続行します。会話形式の Web サービスでは、呼び出しに関連付けられた ID を使用して、会話しているクライアント アプリケーション、永続化するステート、およびリセットするアイドル タイマーを判断します。通常の続行オペレーションは、クライアント アプリケーションからさらに情報を要求するものや、ステータスを要求するものなどです。
終了 - クライアント アプリケーションは、会話が終了すると明示的に終了オペレーションを呼び出します。Web サービスがその後、その会話と関連付けられたすべてのデータまたはリソースを、削除済みとしてマークします。
会話は通常、2 つの WebLogic Web サービス間で発生します。そのうち 1 つは会話形式のものとしてマークされ、開始、続行、および終了のオペレーションを定義します。もう 1 つの Web サービスは @ServiceClient
アノテーションを使用して、それが会話形式の Web サービスのクライアントであることを指定します。また、制限事項はありますが、会話形式の Web サービスはスタンドアロン Java クライアントからも呼び出せます。
他の WebLogic Web サービスの機能と同様に、Web サービスを会話形式のものとして指定するには、JWS アノテーションを使用します。
注意 : 会話形式の Web サービスを呼び出すクライアント Web サービスは、必ずしも会話形式にする必要はありません。ただし、クライアントが会話形式でない場合は、このクライアントの複数のインスタンスが同じ会話形式の Web サービス スタブにアクセスする危険性があり、保存されている会話状態が破損するおそれがあります。この危険性があると判断した場合は、クライアント Web サービスも会話形式になるように指定してください。その場合は、スタンドアロンの Java クライアントは使用できません。これは、WebLogic API を使用して会話形式であることを指定する方法がないためです。会話形式の Web サービス自体は、必ず 1 回、メッセージの配信が行われることや、メッセージが順序どおりに配信されることを保証するものではありません。そのようなメッセージ配信保証が必要であれば、Web サービスが信頼性のあるものであることも指定する必要があります。「Web サービスの信頼性のあるメッセージングの使用 : 主な手順」および「非同期機能の併用」を参照してください。 |
以下の手順では、会話形式の Web サービス、ならびにクライアント Web サービスおよびスタンドアロン Java クライアント アプリケーション (いずれも会話を開始および実施するもの) を作成する方法について説明します。この手順では、2 つの Web サービスを実装する JWS ファイルをゼロから作成する方法を示しています。既存の JWS ファイルを更新する場合は、この手順をガイドとして利用することもできます。
Ant ベースの開発環境を設定済みであり、かつ jwsc
Ant タスクを実行して、生成された会話形式の Web サービスをデプロイするためのターゲットを追加できる、作業用の build.xml
ファイルがあることが前提となっています。さらに、会話を開始するクライアント Web サービスをホストする、WebLogic Server インスタンスを同様に設定してあることも前提となっています。詳細については、『Oracle Fusion Middleware Oracle WebLogic Server JAX-RPC を使用した Web サービス入門』の以下の節を参照してください。
表 4-1 会話形式の Web サービスの作成手順
# |
手順 | 説明 |
---|---|---|
1 |
会話形式の Web サービスを実装する、新しい JWS ファイルを作成するか、既存の JWS ファイルを更新する。 |
使い慣れた IDE またはテキスト エディタを使用する。「会話形式の JWS ファイルに関するプログラミングのガイドライン」を参照。 |
2 |
会話形式の JWS ファイルを Web サービスにコンパイルする、 |
『Oracle Fusion Middleware Oracle WebLogic Server JAX-RPC を使用した Web サービス入門』の「jwsc WebLogic Web サービス Ant タスクの実行」を参照。 |
3 |
Ant ターゲットを実行して、会話形式の Web サービスをビルドする。 |
例 : prompt> ant build-mainService |
4 |
通常のように、対象 Web サービスをデプロイする。 |
『Oracle Fusion Middleware Oracle WebLogic Server JAX-RPC を使用した Web サービス入門』の「WebLogic Web サービスのデプロイとアンデプロイ」を参照。 |
5 |
クライアント Web サービスを実装する、新しい JWS ファイルを作成するか、既存の JWS ファイルを更新する。 |
クライアント アプリケーションがスタンドアロン Java クライアントである場合は、「会話形式の Web サービスを呼び出すためのスタンドアロン Java クライアントの更新」を参照。手順 6 ~ 9 をスキップする。 クライアント アプリケーション自体が Web サービスである場合は、手順 6 ~ 9 に従う。 |
6 |
会話形式の Web サービスで会話を開始および実施する新しい JWS ファイルを作成するか、既存の JWS ファイルを更新する。 |
使い慣れた IDE またはテキスト エディタを使用する。クライアント Web サービスが、会話形式の Web サービスをホストするものとは別の WebLogic Server インスタンスにデプロイされていることが前提となる。「会話形式の Web サービスを呼び出す JWS ファイルに関するプログラミングのガイドライン」を参照。 |
7 |
クライアント Web サービスをビルドする |
|
8 |
Ant ターゲットを実行して、クライアント Web サービスをビルドする。 |
例 : prompt> ant build-clientService |
9 |
通常のように、クライアント Web サービスをデプロイする。 |
『Oracle Fusion Middleware Oracle WebLogic Server JAX-RPC を使用した Web サービス入門』の「WebLogic Web サービスのデプロイとアンデプロイ」を参照。 |
次のサンプルでは、会話形式の Web サービスを実装する簡単な JWS ファイルを示します。太字で示された Java コードに対応するコーディングのガイドラインについては、サンプルの後の説明を参照してください。
package examples.webservices.conversation; import java.io.Serializable; import weblogic.jws.WLHttpTransport; import weblogic.jws.Conversation; import weblogic.jws.Conversational; import weblogic.jws.Context; import weblogic.wsee.jws.JwsContext; import weblogic.wsee.jws.ServiceHandle; import javax.jws.WebService; import javax.jws.WebMethod; @Conversational(maxIdleTime="10 minutes", maxAge="1 day", runAsStartUser=false, singlePrincipal=false ) @WebService(name="ConversationalPortType", serviceName="ConversationalService", targetNamespace="http://examples.org/") @WLHttpTransport(contextPath="conv", serviceUri="ConversationalService", portName="ConversationalServicePort") /** * 会話形式の Web サービス */ public class ConversationalServiceImpl implements Serializable { @Context private JwsContext ctx; public String status = "undefined"; @WebMethod @Conversation (Conversation.Phase.START) public String start() { ServiceHandle handle = ctx.getService(); String convID = handle.getConversationID(); status = "start"; return "Starting conversation, with ID " + convID + " and status equal to " + status; } @WebMethod @Conversation (Conversation.Phase.CONTINUE) public String middle(String message) { status = "middle"; return "Middle of conversation; the message is: " + message + " and status is " + status; } @WebMethod @Conversation (Conversation.Phase.FINISH) public String finish(String message ) { status = "finish"; return "End of conversation; the message is: " + message + " and status is " + status; } }
会話形式の Web サービスを実装している JWS ファイルをプログラミングする際には、以下のガイドラインに従います。ガイドラインのサンプル コードは、上述のサンプルでは太字で示されています。
会話形式の Web サービスは、java.io.Serializable
を実装していなければならないので、まず JWS ファイルにクラスをインポートする必要がある。
import java.io.Serializable;
会話形式の JWS アノテーションをインポートする。
import weblogic.jws.Conversation; import weblogic.jws.Conversational;
会話形式の Web サービスの実行時情報にアクセスする場合は、@Context
アノテーションおよびコンテキスト API をインポートする。
import weblogic.jws.Context; import weblogic.wsee.jws.JwsContext; import weblogic.wsee.jws.ServiceHandle;
実行時 Web サービスのコンテキストの詳細については、『Oracle Fusion Middleware Oracle WebLogic Server JAX-RPC を使用した Web サービス入門』の「Web サービスの実行時情報へのアクセス」を参照してください。
クラス レベルの @Conversational
アノテーションを使用して、Web サービスを会話形式のものであると指定する。このアノテーションは任意指定ですが (メソッド レベルの @Conversation
アノテーションを指定していると仮定した場合)、常にこれを JWS ファイル内で使用して、Web サービスが会話形式であると明確に指定することをお勧めします。
指定する任意の属性は、WebLogic Server が会話を終了するまでの、Web サービスがアイドル状態でいられる最大時間 maxIdleTime
、会話の最大存続期間 maxAge
、既存の会話の続行フェーズと終了フェーズを、会話を開始したユーザとして実行するかどうかを示す runAsStartUser
、会話を開始したユーザ以外のユーザが、会話の続行フェーズと終了フェーズの実行を許可されるかどうかを示す singlePrincipal
のうちのいずれかです。
@Conversational(maxIdleTime="10 minutes", maxAge="1 day", runAsStartUser=false, singlePrincipal=false )
JWS ファイルに @Conversational
アノテーションが含まれている場合、Web サービスのすべてのオペレーションが会話形式です。オペレーションのデフォルトのフェーズは、明示的に @Conversation
アノテーションが指定されていなければ、続行フェーズです。ただし、会話形式の Web サービスには、1 つ以上の開始オペレーションと、1 つの終了オペレーションが含まれていることが必要なので、メソッド レベルの @Conversation
アノテーションを使用して、これらのオペレーションをどのメソッドで実装するかを指定する必要があります。
属性のデフォルト値の詳細については、『Oracle Fusion Middleware Oracle WebLogic Server Web サービス リファレンス』の「weblogic.jws.Conversational」を参照してください。
JWS ファイルには、java.io.Serializable
が実装されている必要がある。
public class ConversationalServiceImpl implements Serializable {
Web サービスの実行時情報にアクセスするには、データ型 weblogic.wsee.jws.JwsContext
のプライベート クラス変数に、フィールド レベルの @Context
JWS アノテーションを付ける。
@Context private JwsContext ctx;
@Conversation
アノテーションを使用して、会話の開始、続行、および終了フェーズを実装するメソッドを指定する。会話には、1 つ以上の開始オペレーションと、1 つの終了オペレーションが必要である。続行オペレーションは任意指定である。フェーズを指定するアノテーションには、Conversation.Phase.START
、Conversation.Phase.CONTINUE
、または Conversation.Phase.FINISH
の各パラメータを使用します。次の例では、開始オペレーションを指定している。
@WebMethod @Conversation (Conversation.Phase.START) public String start() {...
@Conversation
アノテーションでマークする JWS ファイルのメソッドが 1 つのみの場合、Web サービス全体が会話形式となり、各オペレーションは、会話の一部と見なされます。これは、JWS ファイルで任意指定のクラス レベル @Conversational
アノテーションを使用していなかった場合でも当てはまります。@Conversational
で明示的にアノテーション付きにされていないメソッドはすべて、デフォルトで続行オペレーションとなります。つまり、たとえばクライアント アプリケーションが、それ以前に開始オペレーションを呼び出していない状態でこれらの続行メソッドの 1 つを呼び出すと、Web サービスが実行時エラーを返すということです。
なお、スタンドアロン Java クライアントから会話形式の Web サービスを呼び出す場合、開始オペレーションは要求と応答であることが必要です。言い換えると、このオペレーションに、@Oneway
JWS アノテーションを付けることはできません。オペレーションは、void
を返すことがあります。Web サービスを、WebLogic Server で実行されているクライアント アプリケーションからのみ呼び出す場合、この要件は適用されません。
詳細については、『Oracle Fusion Middleware Oracle WebLogic Server Web サービス リファレンス』の「weblogic.jws.Conversation」を参照してください。
Web サービスの実行時情報を取得するには、JwsContext
インスタンスを使用する。
たとえば、開始オペレーションの次のコードでは、WebLogic Server が新しい会話に割り当てる ID を取得します。
ServiceHandle handle = ctx.getService(); String convID = handle.getConversationID();
コンテキスト関連の API の使用の詳細については、『Oracle Fusion Middleware Oracle WebLogic Server JAX-RPC を使用した Web サービス入門』の「Web サービスの実行時情報へのアクセス」を参照してください。
次の例では、「会話形式の JWS ファイルに関するプログラミングのガイドライン」で説明した会話形式の Web サービスを呼び出す Web サービス用の簡単な JWS ファイルを示します。太字で示された Java コードに対応するコーディングのガイドラインについては、サンプルの後の説明を参照してください。
package examples.webservices.conversation; import weblogic.jws.WLHttpTransport; import weblogic.jws.ServiceClient; import weblogic.wsee.conversation.ConversationUtils; import javax.jws.WebService; import javax.jws.WebMethod; import javax.xml.rpc.Stub; import examples.webservices.conversation.ConversationalPortType; import java.rmi.RemoteException; @WebService(name="ConversationalClientPortType", serviceName="ConversationalClientService", targetNamespace="http://examples.org/") @WLHttpTransport(contextPath="convClient", serviceUri="ConversationalClient", portName="ConversationalClientPort") /** * ConversationalService と会話を行うクライアント */ public class ConversationalClientImpl { @ServiceClient( wsdlLocation="http://localhost:7001/conv/ConversationalService?WSDL", serviceName="ConversationalService", portName="ConversationalServicePort") private ConversationalPortType port; @WebMethod public void runConversation(String message) { try { // 開始オペレーションを呼び出す String result = port.start(); System.out.println("start method executed."); System.out.println("The message is: " + result); // 続行オペレーションを呼び出す result = port.middle(message ); System.out.println("middle method executed."); System.out.println("The message is: " + result); // 終了オペレーションを呼びす result = port.finish(message ); System.out.println("finish method executed."); System.out.println("The message is: " + result); ConversationUtils.renewStub((Stub)port); } catch (RemoteException e) { e.printStackTrace(); } } }
会話形式の Web サービスを呼び出す JWS ファイルをプログラミングする際には、以下のガイドラインに従います。ガイドラインのサンプル コードは、上述のサンプル内では太字で示されています。
@ServiceClient
JWS アノテーションをインポートする。
import weblogic.jws.ServiceClient;
必要に応じて、会話をさらにコンフィグレーションするための WebLogic ユーティリティ クラスをインポートする。
import weblogic.wsee.conversation.ConversationUtils;
呼び出したい会話形式の Web サービスのポート タイプの JAX-RPC スタブをインポートする。実際のスタブそのものは、後で jwsc
Ant タスクによって作成される。スタブ パッケージは、<jws>
の子要素 <clientgen>
の packageName
属性によって指定され、スタブの名前は呼び出された Web サービスの WSDL によって決まる。
import examples.webservices.conversation.ConversationalPortType;
JWS ファイルの本文で、@ServiceClient
JWS アノテーションを使用して、呼び出したい会話形式の Web サービスの WSDL、名前、およびポートを指定する。このアノテーションは、プライベート変数のフィールド レベルで指定します。この変数のデータ型は、呼び出している Web サービスの JAX-RPC ポート タイプとなる。
@ServiceClient( wsdlLocation="http://localhost:7001/conv/ConversationalService?WSDL", serviceName="ConversationalService", portName="ConversationalServicePort") private ConversationalPortType port;
@ServiceClient
アノテーションを付けたスタブを使用して、会話形式の Web サービスの開始オペレーションを呼び出し、会話を開始する。開始メソッドは、JWS ファイルの任意の場所 (コンストラクタ、メソッドなど) から呼び出せる。
String result = port.start();
必要に応じて続行メソッドを呼び出し、会話を続行する。開始したものと同じ会話が続行されるよう、必ず同じスタブ インスタンスを使用する。
result = port.middle(message );
会話が完了したら、会話形式の Web サービスが現在の会話に使用していたリソースを解放できるよう、終了オペレーションを呼び出す。
result = port.finish(message );
Web サービスの会話スタブを再利用して新しい会話を開始したい場合は、weblogic.wsee.conversation.ConversationUtils
ユーティリティ クラスの renewStub()
メソッドを使用して、そのスタブを明示的に更新する必要がある。
ConversationUtils.renewStub((Stub)port);
注意 : 会話形式の Web サービスを呼び出すクライアント Web サービスは、必ずしも会話形式にする必要はありません。ただし、クライアントが会話形式でない場合は、このクライアントの複数のインスタンスが同じ会話形式の Web サービス スタブにアクセスする危険性があり、保存されている会話状態が破損するおそれがあります。この危険性があると判断した場合は、クライアント Web サービスも会話形式になるように指定してください。 |
WebLogic Server には、会話機能で使用するユーティリティ クラスが用意されています。このクラスを使用すると、会話 ID の取得や設定、コンフィグレーション オプションの設定といった一般的なタスクを実行できます。これらのタスクには、会話形式の Web サービス内で実行するものと、会話形式の Web サービスを呼び出すクライアント内で実行するものがあります。このクラスの使用例については、「会話形式の Web サービスを呼び出す JWS ファイルに関するプログラミングのガイドライン」を参照してください。
詳細については、『Oracle Fusion Middleware Oracle WebLogic Server 10.3.1 API リファレンス』の「weblogic.wsee.conversation.ConversationUtils」を参照してください。
build.xml
ファイルを更新して、会話形式の Web サービスを呼び出す JWS ファイルを生成するには、次のサンプルのような taskdefs
および build-clientService
ターゲットを追加します。詳細については、サンプルの後の説明を参照してください。
<taskdef name="jwsc" classname="weblogic.wsee.tools.anttasks.JwscTask" /> <target name="build-clientService"> <jwsc enableAsyncService="true" srcdir="src" destdir="${clientService-ear-dir}" > <jws file="examples/webservices/conversation/ConversationalClientImpl.java" > <clientgen wsdl="http://${wls.hostname}:${wls.port}/conv/ConversationalService?WSDL" packageName="examples.webservices.conversation"/> </jws> </jwsc> </target>
jwsc
Ant タスクの完全なクラス名を定義するには、taskdef
Ant タスクを使用します。
クライアント Web サービスをコンパイルする jwsc
Ant タスクを更新して、<jws>
要素の <clientgen>
子要素を含めます。これにより、デプロイされた ConversationalService
Web サービスの JAX-RPC スタブが生成およびコンパイルされるようになります。jwsc
Ant タスクでは、これらのスタブが生成された WAR ファイルに自動的にパッケージ化されるため、即座にクライアント Web サービスからアクセスできるようになります。このようにするのは、生成されたクラスの 1 つを ConversationalClientImpl
JWS ファイルでインポートして使用するためです。
次の例では、「会話形式の JWS ファイルに関するプログラミングのガイドライン」で説明した会話形式の Web サービスを呼び出す、簡単なスタンドアロンの Java クライアントを示します。太字で示された Java コードに対応するコーディングのガイドラインについては、サンプルの後の説明を参照してください。
package examples.webservices.conv_standalone.client; import java.rmi.RemoteException; import javax.xml.rpc.ServiceException; import javax.xml.rpc.Stub; import weblogic.wsee.jaxrpc.WLStub; /** * ConversationalService を呼び出し、これと会話するスタンドアロン クライアント */ public class Main { public static void main(String[] args) throws ServiceException, RemoteException{ ConversationalService service = new ConversationalService_Impl(args[0] + "?WSDL"); ConversationalPortType port = service.getConversationalServicePort(); // スタブ上のプロパティを設定して、クライアントが高度な機能を使用する Web // サービスを呼び出していることを指定する。このプロパティは、クライアントが // WebLogic Server インスタンスで実行されている場合には自動的に設定される Stub stub = (Stub)port; stub._setProperty(WLStub.COMPLEX, "true"); // 開始オペレーションを呼び出して会話を開始する String result = port.start(); System.out.println("start method executed."); System.out.println("The message is: " + result); // 続行オペレーションを呼び出す result = port.middle("middle" ); System.out.println("middle method executed."); System.out.println("The message is: " + result); // 終了オペレーションを呼びす result = port.finish("finish" ); System.out.println("finish method executed."); System.out.println("The message is: " + result); } }
会話形式の Web サービスを呼び出すスタンドアロン Java クライアントをプログラミングする際には、以下のガイドラインに従います。ガイドラインのサンプル コードは、上述のサンプルでは太字で示されています。
weblogic.wsee.jaxrpc.WLStub
クラスをインポートする。
import weblogic.wsee.jaxrpc.WLStub;
_setProperty
メソッドを使用して、WLStub.Complex
プロパティを ConversationalService
の JAX-RPC スタブに対して設定する。
Stub stub = (Stub)port; stub._setProperty(WLStub.COMPLEX, "true");
このプロパティは、クライアントが高度な Web サービス (この場合は会話形式の Web サービス) を呼び出すことを Web サービスのランタイムに対して指定します。このプロパティは、別の WebLogic Web サービスから会話形式の Web サービスを呼び出している場合には、自動的に設定されます。
会話形式の Web サービスの開始オペレーションを呼び出して、会話を開始する。
String result = port.start();
必要に応じて続行メソッドを呼び出し、会話を続行する。
result = port.middle(message );
会話が完了したら、会話形式の Web サービスが現在の会話に使用していたリソースを解放できるよう、終了オペレーションを呼び出す。
result = port.finish(message );
WebLogic Server では、プロダクションの再デプロイメントがサポートされています。つまり、会話形式の WebLogic Web サービスの更新後の新しいバージョンを、同じ Web サービスの古いバージョンと並行してデプロイできます。
WebLogic Server では、新しいクライアントのリクエストのみが新しいバージョンに転送されるように、クライアント接続が自動的に管理されます。再デプロイメント時にすでに Web サービスに接続していたクライアントは、作業が完了するまで古いバージョンのサービスを使用し続けます。作業が完了した時点で、自動的に古い Web サービスが廃止されます。クライアントが会話形式の Web サービスに接続されている場合は、既存の会話がクライアントによって明示的に終了されるか、またはタイムアウトになったときに、そのクライアントの作業が完了したと見なされます。
プロダクションの再デプロイメントと Web サービス クライアントの詳細については、『Oracle Fusion Middleware Oracle WebLogic Server JAX-RPC を使用した Web サービス入門』の「Web サービスを再デプロイする際にクライアントで考慮すべき事項」を参照してください。