| Oracle® Fusion Middleware Oracle WebLogic Server JAX-RPC Webサービスの高度な機能のプログラミング 11g リリース1 (10.3.6) B61634-05 |
|
![]() 前 |
![]() 次 |
この章では、WebLogic Java API for XML-based RPC (JAX-RPC) Webサービスで、SOAPメッセージ・ハンドラを作成および使用する方法について説明します。
この章では、以下のトピックについて説明します。
Webサービスの中には、SOAPメッセージへのアクセスを必要とするものがあります。このSOAPメッセージに対してSOAPメッセージ・ハンドラを作成できます。
SOAPメッセージ・ハンドラは、Webサービスのリクエストとレスポンスの両方でSOAPメッセージをインターセプトするメカニズムです。ハンドラは、WebサービスそのものとWebサービスを呼び出すクライアント・アプリケーションの両方で作成することができます。
ハンドラ使用の簡単な例としては、SOAPメッセージのヘッダー部分の情報へのアクセスがあります。SOAPのヘッダーを使用してWebサービス固有の情報を格納しておき、ハンドラを使用してその情報を操作することができます。
SOAPメッセージ・ハンドラは、Webサービスのパフォーマンスを向上させるために使用することもできます。Webサービスがデプロイされてしばらくすると、同じパラメータを使用してWebサービスを呼び出すコンシューマが多いことに気付く場合があります。よく使用されるWebサービス呼出しの結果をキャッシュしておき(結果が静的であることが前提となります)、適宜、キャッシュしておいた結果をただちに戻すことによって、Webサービスを実装したバックエンド・コンポーネントを呼び出す必要がなくなり、Webサービスのパフォーマンスが向上します。このパフォーマンスの向上は、ハンドラを使用して、SOAPリクエスト・メッセージに頻繁に使用されるパラメータが含まれていないかチェックすることで実現できます。
次の表では、Webサービスでハンドラ・チェーンが構成されていることを指定するためにJWSファイル内で使用できる標準的なJWSアノテーションを示しています。その後の項で、これらのアノテーションの使い方について、より詳細に説明します。詳細は、http://www.jcp.org/en/jsr/detail?id=181にある「Web Services MetaData for the Java Platform (JSR-181)仕様」を参照してください。
表9-1 SOAPメッセージ・ハンドラ・チェーンの構成に使用されるJWSアノテーション
| JWSアノテーション | 説明 |
|---|---|
javax.jws.HandlerChain |
Webサービスを外部で定義されるハンドラ・チェーンと関連付けます。複数のWebサービスで同じハンドラ構成を共有する必要がある場合、またはハンドラ・チェーンが複数のトランスポートのハンドラで構成されている場合は、このアノテーションを使用します。 |
javax.jws.soap.SOAPMessageHandlers |
各Webサービス操作の呼出し前と呼出し後に実行されるSOAPハンドラのリストを指定します。外部構成ファイルを使用するよりも、JWSファイルそのものにハンドラ構成情報を埋め込む方が望ましい場合は、(
注意: このアノテーションは、JAX-RPC Webサービスでのみ機能します。 |
javax.jws.soap.SOAPMessageHandler |
単一のSOAPメッセージ・ハンドラを |
次の表では、javax.xml.rpc.handler APIのメイン・クラスおよびインタフェースについて説明します。これらの一部は、ハンドラそのものの作成時に使用します。これらのAPIについては、後の節でより詳細に説明します。これらのAPIの詳細は、http://java.net/projects/jax-rpc/にある「JAX-RPC 1.1仕様」を参照してください。
表9-2 JAX-RPCハンドラのインタフェースとクラス
| javax.xml.rpc.handlerのインタフェースとクラス | 説明 |
|---|---|
Handler |
ハンドラ作成時に実装される主なインタフェース。SOAPのリクエスト、レスポンス、およびフォルトを処理するメソッドが格納されています。 |
GenericHandler |
|
HandlerChain |
ハンドラのリストを表すインタフェース。 |
HandlerRegistry |
HandlerRegistry内のハンドラのプログラムによる構成に対するサポートを提供するインタフェース。 |
HandlerInfo |
ハンドラ・チェーン内のハンドラの情報が格納されているクラス。 |
MessageContext |
ハンドラによって処理されたメッセージのコンテキストを抽出します。 |
soap.SOAPMessageContext |
SOAPメッセージの取得または更新に使用されるMessageContextインタフェースのサブインタフェース。 |
javax.xml.soap.SOAPMessage |
実際のSOAPのリクエスト・メッセージまたはレスポンス・メッセージが入ったオブジェクト。ヘッダー、本文、添付ファイルが含まれます。 |
次の手順では、WebサービスにSOAPメッセージ・ハンドラを追加する手順を大まかに説明します。
Webサービスを実装する基本的なJWSファイルを作成済であり、SOAPメッセージ・ハンドラおよびハンドラ・チェーンを追加してWebサービスを更新することが前提となっています。また、Antベースの開発環境を設定済であり、かつjwsc Antタスクを実行するためのターゲットを含む、作業用のbuild.xmlファイルがあることも前提となっています。詳細は、『Oracle WebLogic Server JAX-RPC Webサービス・スタート・ガイド』を参照してください。
使用例とサンプル
WebLogic Webサービスの開発
JWSファイルのプログラミング
Webサービスの呼出し
表9-3 WebサービスへのSOAPメッセージ・ハンドラの追加手順
| # |
手順 | 説明 |
|---|---|---|
|
1 |
ハンドラとハンドラ・チェーンを設計します。 |
「SOAPメッセージ・ハンドラおよびハンドラ・チェーンの設計」を参照してください。 |
|
2 |
ハンドラ・チェーン内の各ハンドラについて、 |
「GenericHandlerクラスの作成」を参照してください。 |
|
3 |
SOAPメッセージ・ハンドラを構成するためのアノテーションを追加して、JWSファイルを更新します。 |
「JWSファイルでのハンドラの構成」を参照してください。 |
|
4 |
JWSファイル内で |
「ハンドラ・チェーン構成ファイルの作成」を参照してください。 |
|
5 |
ハンドラ・チェーン内のすべてのハンドラ・クラスをコンパイルし、Webサービスを再ビルドします。 |
「Webサービスのコンパイルと再ビルド」を参照してください。 |
クライアント側のSOAPメッセージ・ハンドラおよびハンドラ・チェーンの作成については、「クライアント側SOAPメッセージ・ハンドラの作成と使用」を参照してください。
SOAPメッセージ・ハンドラおよびハンドラ・チェーンを設計するときには、以下の事項を決定する必要があります。
すべての作業を実行するために必要なハンドラの数
実行の順序
ハンドラ・チェーン内の各ハンドラには、SOAPのリクエスト・メッセージを処理するメソッドとSOAPのレスポンス・メッセージを処理するメソッドが1つずつあります。順序付けされたハンドラのグループが、ハンドラ・チェーンです。Webサービスに、@HandlerChainと@SOAPMessageHandlerという2つのJWSアノテーションのうち1つを備えるハンドラ・チェーンが付加されていることを指定します。どちらをいつ使用するかは、後の項で説明します。
Webサービスを呼び出すときに、WebLogic Serverは次のようにハンドラを実行します。
ハンドラ・チェーン内のハンドラのhandleRequest()メソッドはすべて、JWSアノテーションで指定されている順序で実行されます。これらのhandleRequest()メソッドのいずれもが、SOAPのリクエスト・メッセージを変更できます。
ハンドラ・チェーン内の最後のハンドラのhandleRequest()メソッドが実行されると、WebLogic Serverは、Webサービスを実装するバックエンド・コンポーネントを呼び出し、最終的なSOAPのリクエスト・メッセージを渡します。
バックエンド・コンポーネントの実行が終了したら、ハンドラ・チェーン内のハンドラのhandleResponse()メソッドが、JWSアノテーションで指定されているのとは逆の順序で実行されます。これらのhandleResponse()メソッドのいずれもが、SOAPのレスポンス・メッセージを変更できます。
ハンドラ・チェーン内の最初のハンドラのhandleResponse()メソッドが実行されると、WebLogic Serverは、Webサービスを呼び出したクライアント・アプリケーションに最終的なSOAPレスポンス・メッセージを戻します。
たとえば、JWSファイルで@HandlerChain JWSアノテーションを使用して外部構成ファイルを指定することになっており、その構成ファイルでは、次の例に示す3つのハンドラが格納されたSimpleChainというハンドラ・チェーンを定義していると仮定します。
<jwshc:handler-config xmlns:jwshc="http://www.bea.com/xml/ns/jws"
xmlns:soap1="http://HandlerInfo.org/Server1"
xmlns:soap2="http://HandlerInfo.org/Server2"
xmlns="http://java.sun.com/xml/ns/j2ee" >
<jwshc:handler-chain>
<jwshc:handler-chain-name>SimpleChain</jwshc:handler-chain-name>
<jwshc:handler>
<handler-name>handlerOne</handler-name>
<handler-class>examples.webservices.soap_handlers.global_handler.ServerHandler1</handler-class>
</jwshc:handler>
<jwshc:handler>
<handler-name>handlerTwo</handler-name>
<handler-class>examples.webservices.soap_handlers.global_handler.ServerHandler2</handler-class>
</jwshc:handler>
<jwshc:handler>
<handler-name>handlerThree</handler-name>
<handler-class>examples.webservices.soap_handlers.global_handler.ServerHandler3</handler-class>
</jwshc:handler>
</jwshc:handler-chain>
</jwshc:handler-config>
次の図は、WebLogic Serverで各ハンドラのhandleRequest()メソッドとhandleResponse()メソッドが実行される順序を示しています。
通常、着信メッセージと発信メッセージで同じタイプの処理が必要となるので、各SOAPメッセージ・ハンドラには、リクエストSOAPメッセージとレスポンスSOAPメッセージを処理する別個のメソッドがあります。たとえば、SOAPリクエストにあるセキュア・データを復号化するhandleRequest()メソッドと、SOAPレスポンスを暗号化するhandleResponse()メソッドを持つ暗号化ハンドラを設計する場合があります。
一方、SOAPリクエストのみを処理し、それと同等のレスポンス処理は行わないハンドラを設計することもできます。
また、ハンドラ・チェーン内の次のハンドラを呼び出さず、そのまま、任意の時点でクライアント・アプリケーションにレスポンスを送信することも可能です。
SOAPメッセージ・ハンドラ・クラスでは、javax.rpc.xml.handler.GenericHandler抽象クラスを拡張する必要があります。この抽象クラス自体が、javax.rpc.xml.handler.Handlerインタフェースを実装します。
GenericHandlerクラスは、ハンドラの記述を容易にする便利な抽象クラスです。このクラスは、ライフサイクル・メソッドinit()およびdestroy()ならびにHandlerインタフェースの様々なhandleXXX()メソッドのデフォルト実装を提供します。ハンドラ・クラスを記述する際には、Handler実装クラスの一部としてカスタマイズが必要なメソッドのみをオーバーライドします。
特に、Handlerインタフェースには、GenericHandlerを拡張するハンドラ・クラス内で実装できる、次のメソッドが格納されています。
init()
「Handler.init()メソッドの実装」を参照してください。
destroy()
「Handler.destroy()メソッドの実装」を参照してください。
getHeaders()
「Handler.getHeaders()メソッドの実装」を参照してください。
handleRequest()
「Handler.handleRequest()メソッドの実装」を参照してください。
handleResponse()
「Handler.handleResponse()メソッドの実装」を参照してください。
handleFault()
「Handler.handleFault()メソッドの実装」を参照してください。
特に画像などの添付ファイルを処理する場合などには、ハンドラ内から直接SOAPメッセージを表示または更新しなければならない場合もあります。その場合には、javax.xml.soap.SOAPMessage抽象クラスを使用します。このクラスは、SOAP With Attachments API for Java 1.1 (SAAJ)仕様(http://java.net/projects/saaj/)に含まれています。詳細については、「SAAJを使用したSOAPリクエスト・メッセージおよびレスポンス・メッセージの直接操作」を参照してください。
次の例は、SOAPのリクエストおよびレスポンス・メッセージをWebLogic Serverのログ・ファイルに出力する簡単なSOAPメッセージ・ハンドラを示しています。
package examples.webservices.soap_handlers.global_handler;
import javax.xml.namespace.QName;
import javax.xml.rpc.handler.HandlerInfo;
import javax.xml.rpc.handler.GenericHandler;
import javax.xml.rpc.handler.MessageContext;
import javax.xml.rpc.handler.soap.SOAPMessageContext;
import javax.xml.rpc.JAXRPCException;
import weblogic.logging.NonCatalogLogger;
/**
* This class implements a handler in the handler chain, used to access the SOAP
* request and response message.
* <p>
* This class extends the <code>javax.xml.rpc.handler.GenericHandler</code>
* abstract classs and simply prints the SOAP request and response messages to
* the server log file before the messages are processed by the backend
* Java class that implements the Web Service itself.
*/
public class ServerHandler1 extends GenericHandler {
private NonCatalogLogger log;
private HandlerInfo handlerInfo;
/**
* Initializes the instance of the handler. Creates a nonCatalogLogger to
* log messages to.
*/
public void init(HandlerInfo hi) {
log = new NonCatalogLogger("WebService-LogHandler");
handlerInfo = hi;
}
/**
* Specifies that the SOAP request message be logged to a log file before the
* message is sent to the Java class that implements the Web Service.
*/
public boolean handleRequest(MessageContext context) {
SOAPMessageContext messageContext = (SOAPMessageContext) context;
System.out.println("** Request: "+messageContext.getMessage().toString());
log.info(messageContext.getMessage().toString());
return true;
}
/**
* Specifies that the SOAP response message be logged to a log file before the
* message is sent back to the client application that invoked the Web
* service.
*/
public boolean handleResponse(MessageContext context) {
SOAPMessageContext messageContext = (SOAPMessageContext) context;
System.out.println("** Response: "+messageContext.getMessage().toString());
log.info(messageContext.getMessage().toString());
return true;
}
/**
* Specifies that a message be logged to the log file if a SOAP fault is
* thrown by the Handler instance.
*/
public boolean handleFault(MessageContext context) {
SOAPMessageContext messageContext = (SOAPMessageContext) context;
System.out.println("** Fault: "+messageContext.getMessage().toString());
log.info(messageContext.getMessage().toString());
return true;
}
public QName[] getHeaders() {
return handlerInfo.getHeaders();
}
}
Handler.init()メソッドは、Handlerオブジェクトのインスタンスを作成し、そのインスタンスが自動的に初期化されるようにするために呼び出されます。そのシグネチャは次のとおりです。
public void init(HandlerInfo config) throws JAXRPCException {}
HandlerInfoオブジェクトには、SOAPメッセージ・ハンドラ情報、特に初期化パラメータが格納されています。HandlerInfo.getHandlerConfig()メソッドを使用してパラメータを取得すると、このメソッドは、名前と値のペアの入ったjava.util.Mapオブジェクトを返します。
初期化パラメータを処理する必要がある場合、または、他の初期化タスクを実行する必要がある場合は、init()メソッドを実装します。
初期化パラメータの使用例としては、デバッグのオン、オフ、メッセージやエラーを書き込むためのログ・ファイルの名前の指定などがあります。
Handler.destroy()メソッドは、Handlerオブジェクトのインスタンスを破棄するために呼び出されます。そのシグネチャは次のとおりです。
public void destroy() throws JAXRPCException {}
destroy()メソッドを実装すると、ハンドラのライフサイクルを通じて取得されたあらゆるリソースを解放できます。
Handler.getHeaders()メソッドは、このHandlerインスタンスで処理できるヘッダー・ブロックを取得します。そのシグネチャは次のとおりです。
public QName[] getHeaders() {}
Handler.handleRequest()メソッドは、バックエンド・コンポーネントによって処理される前にSOAPのリクエスト・メッセージをインターセプトするために呼び出されます。そのシグネチャは次のとおりです。
public boolean handleRequest(MessageContext mc)
throws JAXRPCException,SOAPFaultException {}
このメソッドを実装すると、バックエンド・コンポーネントによって処理される前のSOAPメッセージ内のデータの復号化などのタスクが実行できます。
MessageContextオブジェクトは、SOAPメッセージ・ハンドラによって処理されたメッセージのコンテキストを抽出します。MessageContextプロパティにより、ハンドラ・チェーン内のハンドラは処理ステートを共有できます。
MessageContextのSOAPMessageContextサブインタフェースを使用すると、SOAPのリクエスト・メッセージの内容を取得または更新することができます。SOAPのリクエスト・メッセージそのものは、javax.xml.soap.SOAPMessageオブジェクトに格納されます。このオブジェクトの詳細は、「SAAJを使用してSOAPリクエスト・メッセージおよびレスポンス・メッセージの直接操作」を参照してください。
SOAPMessageContextクラスは、SOAPリクエストを処理する次の2つのメソッドを定義します。
SOAPMessageContext.getMessage(): SOAPのリクエスト・メッセージの入ったjavax.xml.soap.SOAPMessageオブジェクトを返します。
SOAPMessageContext.setMessage(javax.xml.soap.SOAPMessage): SOAPのリクエスト・メッセージを変更後、それを更新します。
SOAPリクエストのすべての処理をコーディングしたら、次のシナリオのいずれかをコーディングします。
trueを返すことにより、ハンドラ・リクエスト・チェーン内の次のハンドラを呼び出します。
リクエスト・チェーンの次のハンドラは、@HandlerChainアノテーションによって指定された構成ファイル内の<handler-chain>要素の次の<handler>サブ要素と、@SOAPMessageHandlersアノテーションによって指定された配列内の次の@SOAPMessageHandlerのいずれかとして指定されます。チェーン内のすべてのハンドラが実行されたら、メソッドはWebサービスの構成に応じて、バックエンド・コンポーネントの呼出し、最終的なSOAPのリクエスト・メッセージの送信、または最後のハンドラのhandleResponse()メソッドの呼出しを行います。
falseを返すことにより、ハンドラ・リクエスト・チェーンの処理をブロックします。
ハンドラ・リクエスト・チェーンの処理をブロックすると、Webサービスのこの呼出しについては、バックエンド・コンポーネントは実行されなくなります。Webサービスの一部の呼出しの結果をキャッシュしてあり、そのリストに現在の呼出しも含まれている場合は、この操作が便利な場合があります。
ハンドラ・リクエスト・チェーンの処理は中断されますが、WebLogic Serverが、現在のハンドラから順に、レスポンス・チェーンを呼び出します。たとえば、ハンドラ・チェーンに、handlerAとhandlerBという2つのハンドラがあると想定します。ここで、handlerAのhandleRequest()メソッドは、handlerBの対応するメソッドの前に呼び出されるものとします。handlerAで処理がブロックされると(したがってhandlerBのhandleRequest()メソッドは呼び出されません)、ハンドラ・レスポンス・チェーンはhandlerAで開始され、handlerBのhandleRequest()メソッドも呼び出されません。
javax.xml.rpc.soap.SOAPFaultExceptionをスローして、SOAPフォルトを示します。
handleRequest()メソッドがSOAPFaultExceptionをスローすると、WebLogic Serverは、この例外を取得して、ハンドラ・リクエスト・チェーンの後続の処理を終了し、このハンドラのhandleFault()メソッドを呼び出します。
あらゆるハンドラ固有の実行時エラーに対してJAXRPCExceptionをスローします。
handleRequest()メソッドがJAXRPCExceptionをスローすると、WebLogic Serverは、この例外を取得して、ハンドラ・リクエスト・チェーンの後続の処理を終了し、この例外をWebLogic Serverのログ・ファイルに記録し、このハンドラのhandleFault()メソッドを呼び出します。
Handler.handleResponse()メソッドは、SOAPのレスポンス・メッセージがバックエンド・コンポーネントによって処理された後、Webサービスを呼び出したクライアント・アプリケーションに戻される前に、そのメッセージをインターセプトするために呼び出されます。そのシグネチャは次のとおりです。
public boolean handleResponse(MessageContext mc) throws JAXRPCException {}
このメソッドを実装すると、クライアント・アプリケーションに返される前にSOAPメッセージに含まれているデータを暗号化したり、戻り値に処理を加えたりといったタスクを実行できます。
MessageContextオブジェクトは、SOAPメッセージ・ハンドラによって処理されたメッセージのコンテキストを抽出します。MessageContextプロパティにより、ハンドラ・チェーン内のハンドラは処理ステートを共有できます。
MessageContextのSOAPMessageContextサブインタフェースを使用すると、SOAPのレスポンス・メッセージの内容を取得または更新することができます。SOAPのレスポンス・メッセージそのものは、javax.xml.soap.SOAPMessageオブジェクトに格納されます。「SAAJを使用したSOAPリクエスト・メッセージおよびレスポンス・メッセージの直接操作」を参照してください。
SOAPMessageContextクラスは、SOAPレスポンスを処理する次の2つのメソッドを定義します。
SOAPMessageContext.getMessage(): SOAPのレスポンス・メッセージの入ったjavax.xml.soap.SOAPMessageオブジェクトを返します。
SOAPMessageContext.setMessage(javax.xml.soap.SOAPMessage): SOAPのレスポンス・メッセージを変更後、それを更新します。
SOAPレスポンスのすべての処理をコーディングしたら、次のシナリオのいずれかをコーディングします。
trueを返すことにより、ハンドラ・レスポンス・チェーン内の次のハンドラを呼び出します。
ハンドラ・チェーンの次のレスポンスは、@HandlerChainアノテーションによって指定された構成ファイル内の<handler-chain>要素の前の<handler>サブ要素か、@SOAPMessageHandlersアノテーションによって指定された配列内の前の@SOAPMessageHandlerのいずれかとして指定されます(ハンドラ・チェーン上のレスポンスは、JWSファイルで指定されたのと逆の順序で実行されることに留意してください。詳細については、「SOAPメッセージ・ハンドラおよびハンドラ・チェーンの設計」を参照してください)。
ハンドラ・チェーン内のすべてのハンドラが実行されたら、メソッドは、Webサービスを呼び出したクライアント・アプリケーションに最終的なSOAPのレスポンス・メッセージを戻します。
falseを返すことにより、ハンドラ・レスポンス・チェーンの処理をブロックします。
ハンドラ・レスポンス・チェーンの処理をブロックすると、レスポンス・チェーンにある残りのハンドラが、Webサービスのこの呼出しについては実行されなくなり、現在のSOAPメッセージがクライアント・アプリケーションに戻されます。
あらゆるハンドラ固有の実行時エラーに対してJAXRPCExceptionをスローします。
handleRequest()メソッドがJAXRPCExceptionをスローすると、WebLogic Serverは、この例外を取得して、ハンドラ・リクエスト・チェーンの後続の処理を終了し、この例外をWebLogic Serverのログ・ファイルに記録し、このハンドラのhandleFault()メソッドを呼び出します。
Handler.handleFault()メソッドは、SOAPメッセージ処理モデルに基づいてSOAPフォルトを処理します。そのシグネチャは次のとおりです。
public boolean handleFault(MessageContext mc) throws JAXRPCException {}
このメソッドを実装すると、バックエンド・コンポーネントによって生成されたフォルトのほか、handleResponse()メソッドおよびhandleRequest()メソッドによって生成されたあらゆるSOAPフォルトの処理も扱うことができます。
MessageContextオブジェクトは、SOAPメッセージ・ハンドラによって処理されたメッセージのコンテキストを抽出します。MessageContextプロパティにより、ハンドラ・チェーン内のハンドラは処理ステートを共有できます。
MessageContextのSOAPMessageContextサブインタフェースを使用すると、SOAPメッセージの内容を取得または更新することができます。SOAPメッセージそのものは、javax.xml.soap.SOAPMessageオブジェクトに格納されます。「SAAJを使用したSOAPリクエスト・メッセージおよびレスポンス・メッセージの直接操作」を参照してください。
SOAPMessageContextクラスは、SOAPメッセージを処理する次の2つのメソッドを定義します。
SOAPMessageContext.getMessage(): SOAPメッセージの入ったjavax.xml.soap.SOAPMessageオブジェクトを返します。
SOAPMessageContext.setMessage(javax.xml.soap.SOAPMessage): SOAPのメッセージを変更後、それを更新します。
SOAPフォルトのすべての処理をコーディングしたら、次のいずれかを実行します。
trueを返すことにより、ハンドラ・チェーン内の次のハンドラのhandleFault()メソッドを呼び出します。
falseを返すことにより、ハンドラ・フォルト・チェーンの処理をブロックします。
javax.xml.soap.SOAPMessage抽象クラスは、SOAP With Attachments API for Java 1.1 (SAAJ)仕様に含まれています。(http://java.net/projects/saaj/を参照。)このクラスは、SOAPメッセージ・ハンドラ作成時にSOAPのリクエスト・メッセージおよびレスポンス・メッセージを操作するのに使用します。この節では、SOAPMessageオブジェクトの基本構造とSOAPメッセージの表示および更新に役立つメソッドのいくつかについて説明します。
SOAPMessageオブジェクトは、SOAPPartオブジェクト(SOAP XMLドキュメントそのものが入っている)、または同オブジェクトと添付ファイルで構成されています。
SOAPMessageクラスの詳細な説明については、SAAJに関するJavadocを参照してください。
SOAPPartオブジェクトには、SOAPEnvelopeオブジェクトに格納されたXML SOAPドキュメントが入っています。このオブジェクトは、実際のSOAPのヘッダーと本文を取得するのに使用します。
次のJavaコードのサンプルは、Handlerクラスによって提供されたMessageContextオブジェクトからSOAPメッセージを取り出して、その各部を参照する方法を示しています。
SOAPMessage soapMessage = messageContext.getMessage(); SOAPPart soapPart = soapMessage.getSOAPPart(); SOAPEnvelope soapEnvelope = soapPart.getEnvelope(); SOAPBody soapBody = soapEnvelope.getBody(); SOAPHeader soapHeader = soapEnvelope.getHeader();
javax.xml.soap.AttachmentPartオブジェクトには、SOAPメッセージに対するオプションの添付ファイルが入っています。添付ファイルは、SOAPメッセージの残りの部分とは異なり、XMLフォーマットの必須部分ではないので、その形式は、単純なテキストからイメージ・ファイルまで、さまざまです。
添付ファイルを操作するには、SOAPMessageクラスの以下のメソッドを使用します。
countAttachments(): このSOAPメッセージに含まれている添付ファイルの数を返します。
getAttachments(): すべての添付ファイルを取り出し、(AttachmentPartオブジェクトとして) Iteratorオブジェクトに格納します。
createAttachmentPart(): 他のタイプのObjectからAttachmentPartオブジェクトを作成します。
addAttachmentPart(): 作成されたAttachmentPartオブジェクトをSOAPMessageに追加します。
この節では、添付ファイルjava.awt.ImageにアクセスするSOAPメッセージ・ハンドラを作成すること、およびclientgen Antタスクによって生成されたクライアントJAX-RPCスタブを使用するクライアント・アプリケーションからImageが送信されていることを前提としています。
clientgen Antタスクによって生成されたクライアント・コードでは、添付ファイルjava.awt.Imageはimage/gifではなくtext/xmlのMIMEタイプで、呼び出されるWebLogic Webサービスに送信され、画像は画像を表す整数のストリームにシリアライズされます。特に、このクライアント・コードは次の形式で画像をシリアライズします。
int width
int height
int[] pixels
つまり、受信したImage添付ファイルを操作するSOAPメッセージ・ハンドラでは、このデータ・ストリームをデシリアライズして元の画像を作成し直す必要があるということです。
Webサービスのハンドラ・チェーンを構成するためにJWSファイルで使用できる標準的なアノテーションは、@javax.jws.HandlerChainおよび@javax.jws.soap.SOAPMessageHandlersの2つです。
@javax.jws.HandlerChainアノテーション(この章では簡単にするため@HandlerChainとも呼びます)を使用する場合は、file属性を使用して、Webサービスと関連付けるハンドラ・チェーンの構成が含まれた外部ファイルを指定します。構成には、チェーン内のハンドラのリスト、ハンドラが実行される順序、初期化パラメータなどが含まれます。
以下の条件の1つ以上が適用される場合は、@SOAPMessageHandlersアノテーションではなく@HandlerChainアノテーションをJWSファイルで使用します:
複数のWebサービスで同じ構成を共有したい。
ハンドラ・チェーンに、複数のトランスポートのハンドラが含まれている。
Webサービスを実装するJWSファイルを再コンパイルしないで、そのWebサービスのハンドラ・チェーン構成を変更できるようにしたい。
次のJWSファイルでは、@HandlerChainアノテーションの使用例を示します。関連のJavaコードは太字で示しています。
package examples.webservices.soap_handlers.global_handler; import java.io.Serializable; import javax.jws.HandlerChain; import javax.jws.WebService; import javax.jws.WebMethod; import javax.jws.soap.SOAPBinding; import weblogic.jws.WLHttpTransport; @WebService(serviceName="HandlerChainService", name="HandlerChainPortType") // Standard JWS annotation that specifies that the handler chain called // "SimpleChain", configured in the HandlerConfig.xml file, should fire // each time an operation of the Web Service is invoked. @HandlerChain(file="HandlerConfig.xml", name="SimpleChain") @SOAPBinding(style=SOAPBinding.Style.DOCUMENT, use=SOAPBinding.Use.LITERAL, parameterStyle=SOAPBinding.ParameterStyle.WRAPPED) @WLHttpTransport(contextPath="HandlerChain", serviceUri="HandlerChain", portName="HandlerChainServicePort") /** * This JWS file forms the basis of simple Java-class implemented WebLogic * Web Service with a single operation: sayHello. The Web Service also * has a handler chain associated with it, as specified by the * @HandlerChain annotation. */ public class HandlerChainImpl { public String sayHello(String input) { weblogic.utils.Debug.say( "in backend component. input:" +input ); return "'" + input + "' to you too!"; } }
@HandlerChainアノテーションを使用する前に、前述の例に示すように、それをJWSファイルにインポートする必要があります。
@HandlerChainアノテーションのfile属性を使用し、ハンドラ・チェーンの構成情報を含む外部ファイルの名前を指定します。この属性の値はURLです。これは相対でも絶対でもかまいません。相対URLは、ファイルをコンパイルするためにjwsc Antタスクを実行した時点でのJWSファイルの場所を基準とします。
Webサービスと関連付ける構成ファイル内のハンドラ・チェーンの名前を指定するには、name属性を使用します。この属性の値は、構成ファイル内の<handler-chain>要素のname属性に対応します。
|
注意: 1つのJWSファイル内に複数の |
外部構成ファイル作成の詳細は、「ハンドラ・チェーン構成ファイルの作成」を参照してください。
この項で説明した標準的なJWSアノテーションの詳細は、Web Services Metadata for the Java Platform仕様(http://www.jcp.org/en/jsr/detail?id=181)を参照してください。
|
注意: このアノテーションは、Web Services Metadata for the Java Platform仕様(JSR-181)( |
@javax.jws.soap.SOAPMessageHandlers(この項では簡単にするため@SOAPMessageHandlersとも呼びます)アノテーションを使用する場合、JWSファイル自体の中で、Webサービス操作の前と後に実行するSOAPメッセージ・ハンドラの配列を指定します(@SOAPMessageHandlerアノテーションで指定)。@SOAPMessageHandlerアノテーションには、ハンドラのクラス名、初期化パラメータ、ハンドラで処理されるSOAPヘッダーのリストなどを指定する属性が含まれます。JWSファイル自体の内部でハンドラのリストを指定するので、ハンドラ・チェーンの構成はWebサービス内に埋め込まれます。
以下の条件の1つ以上が適用される場合は、@SOAPMessageHandlersアノテーションを使用します:
外部のファイルで構成を指定するのではなく、Webサービス自体の内部にハンドラ・チェーンの構成を埋め込みたい。
ハンドラ・チェーンにSOAPハンドラのみが含まれており、それ以外のトランスポート用のハンドラは含まれていない。
ハンドラ・チェーンの構成を変更するたびにJWSファイルを再コンパイルしたい。
次のJWSファイルでは、@SOAPMessageHandlersアノテーションの簡単な使用例を示します。関連のJavaコードは太字で示しています。
package examples.webservices.soap_handlers.simple; import java.io.Serializable; import javax.jws.soap.SOAPMessageHandlers; import javax.jws.soap.SOAPMessageHandler; import javax.jws.soap.SOAPBinding; import javax.jws.WebService; import javax.jws.WebMethod; import weblogic.jws.WLHttpTransport; @WebService(name="SimpleChainPortType", serviceName="SimpleChainService") // Standard JWS annotation that specifies a list of SOAP message handlers // that exeucte before and after an invocation of all operations in the // Web Serice. @SOAPMessageHandlers ( { @SOAPMessageHandler ( className="examples.webservices.soap_handlers.simple.ServerHandler1"), @SOAPMessageHandler ( className="examples.webservices.soap_handlers.simple.ServerHandler2") } ) @SOAPBinding(style=SOAPBinding.Style.DOCUMENT, use=SOAPBinding.Use.LITERAL, parameterStyle=SOAPBinding.ParameterStyle.WRAPPED) @WLHttpTransport(contextPath="SimpleChain", serviceUri="SimpleChain", portName="SimpleChainServicePort") /** * This JWS file forms the basis of simple Java-class implemented WebLogic * Web Service with a single operation: sayHello. The Web Service also * has a handler chain associated with it, as specified by the * @SOAPMessageHandler/s annotations. */ public class SimpleChainImpl { // by default all public methods are exposed as operations public String sayHello(String input) { weblogic.utils.Debug.say( "in backend component. input:" +input ); return "'" + input + "' to you too!"; } }
@SOAPMessageHandlersアノテーションおよび@SOAPMessageHandlerアノテーションを使用する前に、前述の例に示すように、それらをJWSファイルにインポートする必要があります。これらのアノテーションは、javax.jws.soapパッケージに入っています。
@SOAPMessageHandlers配列で(@SOAPMessageHandlerアノテーションを使用して)ハンドラをリストした順序により、ハンドラの実行の順序(操作前なら順序どおりに、操作後なら逆順で)が指定されます。前述のサンプルでは、ハンドラ・チェーンにおいて2つのハンドラを構成しています。これらのハンドラのクラス名は、examples.webservices.soap_handlers.simple.ServerHandler1とexamples.webservices.soap_handlers.simple.ServerHandler2です。
@SOAPMessageHandlerのinitParams属性を使用すると、特定のハンドラにおいて予期されている初期化パラメータの配列を指定できます。@InitParam標準JWSアノテーションを使用し、次の例のように、名前と値のペアを指定します。
@SOAPMessageHandler(
className = "examples.webservices.soap_handlers.simple.ServerHandler1",
initParams = { @InitParam(name="logCategory", value="MyService")}
)
また、@SOAPMessageHandlerアノテーションには、ハンドラによって実装されるSOAPロールをリストするためのroles属性、およびハンドラによって処理されるSOAPヘッダーをリストするためのheaders属性も含まれています。
|
注意:
|
この項で説明した標準的なJWSアノテーションの詳細は、Web Services Metadata for the Java Platform仕様(http://www.jcp.org/en/jsr/detail?id=181)を参照してください。
JWSファイルで@HandlerChainアノテーションを使用して、ハンドラ・チェーンをWebサービスと関連付けることにした場合は、ハンドラ・チェーン内のハンドラのリスト、それらの実行順、初期化パラメータなどを指定する外部構成ファイルを作成する必要があります。
このファイルはJWSファイルの外部にあるため、この単一の構成ファイルを複数のWebサービスで使用するように構成し、エンタープライズ内のすべてのWebサービスに関してハンドラ構成ファイルを標準化することができます。加えて、すべてのWebサービスを再コンパイルすることなく、ハンドラ・チェーンの構成を変更できます。なお、非SOAPのトランスポートを使用するハンドラ・チェーンにハンドラを入れた場合、@SOAPMessageHandlerアノテーションではなく@HandlerChainアノテーションを使用することが必要となります。
構成ファイルは、次の簡単なサンプルに示すように、XMLを使用して1つまたは複数のハンドラ・チェーンをリストします。
<jwshc:handler-config xmlns:jwshc="http://www.bea.com/xml/ns/jws"
xmlns:soap1="http://HandlerInfo.org/Server1"
xmlns:soap2="http://HandlerInfo.org/Server2"
xmlns="http://java.sun.com/xml/ns/j2ee" >
<jwshc:handler-chain>
<jwshc:handler-chain-name>SimpleChain</jwshc:handler-chain-name>
<jwshc:handler>
<handler-name>handler1</handler-name>
<handler-class>examples.webservices.soap_handlers.global_handler.ServerHandler1</handler-class>
</jwshc:handler>
<jwshc:handler>
<handler-name>handler2</handler-name>
<handler-class>examples.webservices.soap_handlers.global_handler.ServerHandler2</handler-class>
</jwshc:handler>
</jwshc:handler-chain>
</jwshc:handler-config>
この例では、SimpleChainというハンドラ・チェーンに、handler1およびhandler2という2つのハンドラが入っています。これらは<handler-class>要素で指定されるクラス名で実装されます。2つのハンドラは、関連のWebサービス操作の前には昇順で実行され、操作実行後には逆順で実行されます。
ハンドラ初期化パラメータ、ハンドラによって実装されるSOAPロール、およびハンドラによって処理されるSOAPヘッダーを指定するには、それぞれ<handler>要素の<init-param>、<soap-role>、および<soap-header>子要素を使用します。
外部構成ファイルを定義するXMLスキーマ、その作成の詳細、および他のサンプルについては、Web Services Metadata for the Java Platform仕様(http://www.jcp.org/en/jsr/detail?id=181)を参照してください。
この項では、Webサービスをコンパイルおよびビルドする作業用のbuild.xml Antファイルがあり、そのビルド・ファイルを更新してハンドラ・チェーンを含めることを想定しています。このbuild.xmlファイルの作成については、『Oracle WebLogic Server JAX-RPC Webサービス・スタート・ガイド』のWebLogic Webサービスの開発に関する項を参照してください。
メッセージ・ハンドラのコンパイルとビルドが含まれるように開発環境を更新するには、以下のガイドラインに従います。
@HandlerChainまたは@SOAPMessageHandlersアノテーションでJWSファイルを更新後、jwsc Antタスクを再実行して、JWSファイルを再コンパイルし、新しいWebサービスを生成する必要があります。これは、JWSファイル内のアノテーションに変更を加えた場合は常に当てはまります。
JWSファイルで@HandlerChainアノテーションを使用し、jwsc Antタスクを再実行してWebサービスを再生成し、その後、外部構成ファイルのみを変更した場合は、2度目の変更を有効にするためにjwscを再実行する必要はありません。
以下の条件がすべて満たされていれば、jwsc AntタスクはSOAPメッセージ・ハンドラJavaファイルをハンドラ・クラスにコンパイル(およびその後それらを生成されたアプリケーションにパッケージ化)します。
ハンドラ・クラスはJWSファイルの@HandlerChainまたは@SOAPMessageHandler(s)アノテーションにおいて参照されます。
Javaファイルはsourcepath属性で指定されたディレクトリ内に置かれます。
クラスは現在CLASSPATH内に存在しません。
ハンドラ・クラスをjwscで自動的にコンパイルするのではなく、ユーザー側でコンパイルする場合は、jwsc Antタスクを実行する前に、コンパイルされたクラスがCLASSPATH内にあることを確認してください。
ハンドラ・チェーンが関連付けられているWebサービスのデプロイおよび呼出しは、ハンドラ・チェーンのないWebサービスのデプロイおよび呼出しと同様に行います。唯一の相違点は、Webサービスのどの操作を呼び出す場合でも、WebLogic Webサービス・ランタイムは、操作呼出しの前と後の両方で、ハンドラ・チェーン内のハンドラを実行するということです。
ここまでの各項では、WebLogic Serverで動作するWebサービスの一環として実行される、サーバー側SOAPメッセージ・ハンドラを作成する方法について説明してきました。この他に、Webサービス操作を呼び出すクライアント・アプリケーションの一環として実行される、クライアント側ハンドラを作成することもできます。クライアント側ハンドラの場合は、次のタイミングで二度実行されます。
クライアント・アプリケーションがWebサービスにSOAPリクエストを送信する直前
クライアント・アプリケーションがWebサービスからSOAPレスポンスを受信した直後
クライアント側SOAPメッセージ・ハンドラは、スタンドアロン・クライアントと、WebLogic Server内部で実行されるクライアントの、双方のために構成できます。
実際のJavaクライアント側ハンドラは、サーバー側ハンドラと同じ方法、つまりjavax.xml.rpc.handler.GenericHandler抽象クラスを拡張するJavaクラスを記述する方法で作成できます。多くの場合、WebLogic Serverで実行されるWebサービスとそのWebサービスを呼び出すクライアント・アプリケーションで、同じハンドラ・クラスを使用できます。たとえば、サーバーおよびクライアント用として、送信および受信したすべてのSOAPメッセージをログに記録する汎用ロギング・ハンドラ・クラスを記述できます。
サーバー側SOAPハンドラのプログラミングと同様に、クライアント側SOAPメッセージ・ハンドラを呼び出すclientgen AntタスクもXMLファイルを使用して指定します。ただし、次の手順で説明するように、このXMLファイルのXMLスキーマは少し異なります。
次の手順では、Webサービス操作を呼び出すクライアント・アプリケーションにクライアント側SOAPメッセージ・ハンドラを追加する手順を大まかに説明します。
デプロイされたWebサービスを呼び出すクライアント・アプリケーションを作成済であり、クライアント側SOAPメッセージ・ハンドラおよびハンドラ・チェーンを追加してクライアント・アプリケーションを更新することを想定しています。また、Antベースの開発環境を設定済であり、かつclientgen Antタスクを実行するためのターゲットを含む、作業用のbuild.xmlファイルがあることが前提となっています。詳細は、『Oracle WebLogic Server JAX-RPC Webサービス・スタート・ガイド』のスタンドアロン・クライアントからのWebサービスの呼出し: 主な手順に関する項を参照してください。
クライアント側SOAPハンドラと、それらのハンドラの実行順序を指定するハンドラ・チェーンを設計します。この手順は、視点がWebサービスからではなくクライアント・アプリケーションからとなる点を除けば、サーバー側SOAPメッセージ・ハンドラを設計するのとほぼ同じです。
「SOAPメッセージ・ハンドラおよびハンドラ・チェーンの設計」を参照してください。
ハンドラ・チェーン内の各ハンドラについて、javax.xml.rpc.handler.GenericHandler抽象クラスを拡張するJavaクラスを作成します。この手順は、チェーン内のハンドラをサーバーではなくクライアントで実行する点を除けば、サーバー側ハンドラの場合の手順と非常に似ています。
ハンドラ・クラスのプログラミングの詳細は、「GenericHandlerクラスの作成」を参照してください。サンプルについては、「クライアント側ハンドラ・クラスの例」を参照してください。
クライアント側SOAPハンドラの構成ファイルを作成します。このXMLファイルでは、ハンドラ・チェーン内のハンドラ、ハンドラが実行される順序、送信すべき初期化パラメータなどを記述します。
「クライアント側SOAPハンドラの構成ファイルの作成」を参照してください。
クライアント・アプリケーションのビルドに使用するbuild.xmlファイルを更新して、clientgen AntタスクにSOAPハンドラの構成ファイルの名前を指定します。また、build.xmlファイルによってハンドラ・ファイルがJavaクラスにコンパイルされ、クライアント・アプリケーションで使用できる状態になることも確認します。
「クライアント側SOAPハンドラの構成ファイルのclientgenへの指定」を参照してください。
適切なタスクを実行して、クライアント・アプリケーションを再ビルドします。
prompt> ant build-client
次回クライアント・アプリケーションを実行したときには、SOAPリクエスト・メッセージの送信前とレスポンスの受信後に、構成ファイルに記述したSOAPメッセージ・ハンドラが自動的に実行されます。
|
注意:
|
次の例では、Webサービスを呼び出すクライアント・アプリケーション用に構成できる単純なSOAPメッセージ・ハンドラ・クラスを示します。
package examples.webservices.client_handler.client;
import javax.xml.namespace.QName;
import javax.xml.rpc.handler.HandlerInfo;
import javax.xml.rpc.handler.GenericHandler;
import javax.xml.rpc.handler.MessageContext;
public class ClientHandler1 extends GenericHandler {
private QName[] headers;
public void init(HandlerInfo hi) {
System.out.println("in " + this.getClass() + " init()");
}
public boolean handleRequest(MessageContext context) {
System.out.println("in " + this.getClass() + " handleRequest()");
return true;
}
public boolean handleResponse(MessageContext context) {
System.out.println("in " + this.getClass() + " handleResponse()");
return true;
}
public boolean handleFault(MessageContext context) {
System.out.println("in " + this.getClass() + " handleFault()");
return true;
}
public QName[] getHeaders() {
return headers;
}
}
クライアント側SOAPハンドラの構成ファイルでは、ハンドラ・チェーン内のハンドラのリスト、ハンドラが実行される順序、初期化パラメータなどを指定します。このファイルの詳細は、「クライアント側ハンドラの構成ファイル用XMLスキーマ」を参照してください。
この構成ファイルでは、1つまたは複数のハンドラを含む1つのハンドラ・チェーンをXMLで記述します。次に単純な例を示します。
<weblogic-wsee-clientHandlerChain
xmlns="http://www.bea.com/ns/weblogic/90"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:j2ee="http://java.sun.com/xml/ns/j2ee">
<handler>
<j2ee:handler-name>clienthandler1</j2ee:handler-name>
<j2ee:handler-class>examples.webservices.client_handler.client.ClientHandler1</j2ee:handler-class>
<j2ee:init-param>
<j2ee:param-name>ClientParam1</j2ee:param-name>
<j2ee:param-value>value1</j2ee:param-value>
</j2ee:init-param>
</handler>
<handler>
<j2ee:handler-name>clienthandler2</j2ee:handler-name>
<j2ee:handler-class>examples.webservices.client_handler.client.ClientHandler2</j2ee:handler-class>
</handler>
</weblogic-wsee-clientHandlerChain>
この例では、ハンドラ・チェーンに2つのハンドラ(clienthandler1およびclienthandler2)が含まれており、<j2ee:handler-class>要素に指定されたクラス名で実装されています。これら2つのハンドラは、クライアント・アプリケーションがSOAPリクエストをWebサービスに送信する直前に指定の順序で実行され、クライアント・アプリケーションがWebサービスからのSOAPレスポンスを受信した直後に逆の順序で実行されます。
この例では、<j2ee:init-param>要素を使用して1つまたは複数の初期化パラメータをハンドラに指定する方法も示しています。
ハンドラによって実装されるSOAPロール、ハンドラによって処理されるSOAPヘッダー、およびハンドラが関連付けられているWSDLのポート名要素を指定するには、それぞれ、<handler>要素の子要素である<soap-role>、<soap-header>、および<port-name>を使用します。
次のXMLスキーマ・ファイルでは、クライアント側SOAPハンドラの構成ファイルの構造を定義しています。
<?xml version="1.0" encoding="UTF-8"?>
<schema
targetNamespace="http://www.bea.com/ns/weblogic/90"
xmlns:wls="http://www.bea.com/ns/weblogic/90"
xmlns:j2ee="http://java.sun.com/xml/ns/j2ee"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
attributeFormDefault="unqualified"
>
<include schemaLocation="weblogic-j2ee.xsd"/>
<element name="weblogic-wsee-clientHandlerChain"
type="wls:weblogic-wsee-clientHandlerChainType">
<xsd:key name="wsee-clienthandler-name-key">
<xsd:annotation>
<xsd:documentation>
Defines the name of the handler. The name must be unique within the
chain.
</xsd:documentation>
</xsd:annotation>
<xsd:selector xpath="j2ee:handler"/>
<xsd:field xpath="j2ee:handler-name"/>
</xsd:key>
</element>
<complexType name="weblogic-wsee-clientHandlerChainType">
<sequence>
<xsd:element name="handler"
type="j2ee:service-ref_handlerType"
minOccurs="0" maxOccurs="unbounded">
</xsd:element>
</sequence>
</complexType>
</schema>
1つの構成ファイルで、1つのクライアント側ハンドラ・チェーンを指定します。構成ファイルのルートは<weblogic-wsee-clientHandlerChain>で、ファイルにはゼロ個以上の<handler>子要素(それぞれがチェーン内の各ハンドラを記述しています)が含まれます。
<handler>要素の構造は、Java EE 1.4 Web service client XML Schema(http://java.sun.com/xml/ns/j2ee/j2ee_web_services_client_1_1.xsd)で指定されているJava EEのservice-ref_handlerType複合型で記述します。
クライアント側SOAPハンドラの構成ファイルを指定するには、clientgen AntタスクのhandlerChainFile属性を使用します。次に、build.xmlファイルからの抜粋を示します。
<clientgen
wsdl="http://ariel:7001/handlers/ClientHandlerService?WSDL"
destDir="${clientclass-dir}"
handlerChainFile="ClientHandlerChain.xml"
packageName="examples.webservices.client_handler.client"/>
clientgenによって自動的に生成されたJAX-RPCスタブを使用すると、クライアント・アプリケーションがWebサービス操作を呼び出す前と後に、構成ファイルで記述されたハンドラが必ず正しい順序で実行されます。