Oracle® Fusion Middleware Oracle WebLogic Server JAX-WS を使用した Web サービスの高度な機能のプログラミング 11g リリース 1 (10.3.1) B55543-01 |
|
戻る |
次へ |
以下の節では、SOAP メッセージ ハンドラの作成と使用について説明します。
Web サービスおよびそのクライアントは、メッセージのリクエストや応答の追加処理において、SOAP メッセージにアクセスしなければならないときがあります。SOAP メッセージ ハンドラを作成すると、WebLogic Server およびクライアントがこの SOAP メッセージの追加処理を実行することが可能になります。SOAP メッセージ ハンドラは、Web サービスのリクエストと応答の両方で SOAP メッセージをインターセプトするメカニズムです。
ハンドラ使用の簡単な例としては、SOAP メッセージのヘッダ部分の情報へのアクセスがあります。SOAP のヘッダを使用して Web サービス固有の情報を格納しておいて、ハンドラを使用してその情報を操作することができます。
SOAP メッセージ ハンドラは、Web サービスのパフォーマンスを向上させるために使用することもできます。Web サービスがデプロイされてしばらくすると、同じパラメータを使用して Web サービスを呼び出すコンシューマが多いことに気付く場合があります。よく使用される Web サービス呼び出しの結果 (静的な結果を前提として) をキャッシュしておき、Web サービスを実装するバックエンド コンポーネントを呼び出すことなく、適宜、キャッシュしておいた結果をただちに返すことによって、Web サービスのパフォーマンスを向上させることができます。このパフォーマンスの向上は、ハンドラを使用して、SOAP リクエスト メッセージに頻繁に使用されるパラメータが含まれていないかチェックすることで達成されます。
JAX-WS では、SOAP ハンドラと論理ハンドラという 2 つのタイプの SOAP メッセージ ハンドラがサポートされます。SOAP ハンドラは、メッセージのヘッダや本文を含め、SOAP メッセージ全体にアクセスできます。論理ハンドラは、メッセージのペイロードにのみアクセスでき、メッセージ内のプロトコル固有の情報 (たとえばヘッダ) を変更することはできません。
注意 : SOAP ハンドラは、着信メッセージに (セキュリティ、WS-ReliableMessaging、MTOM など) ポリシーと一緒に使用した場合、ユーザ定義のメッセージ ハンドラの実行前に、ポリシーのインターセプタが実行されます。発信メッセージの場合、この順序は逆になります。 |
次の手順では、Web サービスに SOAP メッセージ ハンドラを追加する高度な手順を説明します。
Web サービスを実装する基本的な JWS ファイルを作成済みであり、SOAP メッセージ ハンドラおよびハンドラ チェーンを追加することで Web サービスを更新することが前提となっています。また、Ant ベースの開発環境を設定済みであり、かつ jwsc
Ant タスクを実行するためのターゲットを含む、作業用の build.xml
ファイルがあることが前提となっています。詳細については、『Oracle Fusion Middleware JAX-WS を使用した Oracle WebLogic Server Web サービス入門』を参照してください。
表 8-1 Web サービスに SOAP メッセージ ハンドラを追加する手順
# |
手順 | 説明 |
---|---|---|
1 |
ハンドラとハンドラ チェーンを設計する。 |
SOAP メッセージ ハンドラを設計し、ハンドラ チェーン内でグループ化します。「SOAP メッセージ ハンドラおよびハンドラ チェーンの設計」を参照してください。 |
2 |
ハンドラ チェーン内のハンドラごとに、SOAP メッセージ ハンドラ インタフェースを実装する Java クラスを作成する。 |
「SOAP メッセージ ハンドラの作成」を参照してください。 |
3 |
SOAP メッセージ ハンドラをコンフィグレーションするためのアノテーションを追加して、JWS ファイルを更新する。 |
「JWS ファイルでのハンドラ チェーンのコンフィグレーション」を参照してください。 |
4 |
ハンドラ チェーン コンフィグレーション ファイルを作成する。 |
「ハンドラ チェーン コンフィグレーション ファイルの作成」を参照してください。 |
5 |
ハンドラ チェーン内のすべてのハンドラ クラスをコンパイルし、Web サービスを再ビルドする。 |
「Web サービスのコンパイルと再ビルド」を参照してください。 |
クライアントサイド SOAP メッセージ ハンドラは、スタンドアロン クライアントと、WebLogic Server 内部で実行されるクライアントの、双方のためにコンフィグレーションできます。実際の Java クライアントサイド ハンドラは、サーバサイド ハンドラと同じ方法、つまり、SOAP メッセージ ハンドラ インタフェースを実装する Java クラスを作成する方法で作成できます。多くの場合、WebLogic Server で実行される Web サービスとその Web サービスを呼び出すクライアント アプリケーションで、同じハンドラ クラスを使用できます。たとえば、サーバおよびクライアント用として、送信および受信したすべての SOAP メッセージをログに記録する汎用ロギング ハンドラ クラスを記述できます。
次の手順では、Web サービス オペレーションを呼び出すクライアント アプリケーションにクライアントサイド SOAP メッセージ ハンドラを追加する高度な手順を説明します。
デプロイされた Web サービスを呼び出すクライアント アプリケーションを作成済みであり、クライアントサイド SOAP メッセージ ハンドラおよびハンドラ チェーンを追加することでクライアント アプリケーションを更新することを想定しています。また、Ant ベースの開発環境を設定済みであり、かつ clientgen
Ant タスクを実行するためのターゲットを含む、作業用の build.xml
ファイルがあることが前提となっています。詳細については、『Oracle Fusion Middleware JAX-WS を使用した Oracle WebLogic Server Web サービス入門』の「スタンドアロン クライアントからの Web サービスの呼び出し : 主な手順」を参照してください。
表 8-2 クライアントサイド SOAP メッセージ ハンドラを使用する手順
# |
手順 | 説明 |
---|---|---|
1 |
ハンドラとハンドラ チェーンを設計する。 |
この手順は、サーバサイド SOAP メッセージ ハンドラを設計する手順と似ていますが、視点が Web サービスからではなくクライアント アプリケーションからとなる点が異なります。「SOAP メッセージ ハンドラおよびハンドラ チェーンの設計」を参照してください。 |
2 |
ハンドラ チェーン内のハンドラごとに、SOAP メッセージ ハンドラ インタフェースを実装する Java クラスを作成する。 |
この手順は、サーバサイド SOAP メッセージ ハンドラを設計する手順と似ていますが、視点が Web サービスからではなくクライアント アプリケーションからとなる点が異なります。ハンドラ クラスのプログラミングの詳細については、「SOAP メッセージ ハンドラの作成」を参照してださい。 |
3 |
クライアントを更新して、SOAP メッセージ ハンドラをプログラム的にコンフィグレーションする。 |
「クライアントサイド SOAP メッセージ ハンドラのコンフィグレーション」を参照してください。 |
4 |
アプリケーションのビルドに使用する build.xml ファイルを更新して、clientgen Ant タスクにカスタマイズ ファイルを指定する。 |
「Web サービスのコンパイルと再ビルド」を参照してください。 |
5 |
適切なタスクを実行して、クライアント アプリケーションを再ビルドする。 |
prompt> ant build-client |
次回クライアント アプリケーションを実行したときには、SOAP リクエスト メッセージの送信前と応答の受信後に、コンフィグレーション ファイルに記述した SOAP メッセージ ハンドラが自動的に実行されます。
注意 : clientgen Ant タスクにハンドラのコンフィグレーション ファイルが指定されている限り、クライアントサイド SOAP メッセージ ハンドラを呼び出すために実際のクライアント アプリケーションを更新する必要はありません。ハンドラは、生成されたインタフェースによって自動的に正しい順序で実行されます。 |
SOAP メッセージ ハンドラを設計するときには、以下の事項を決定する必要があります。
作業を実行するために必要なハンドラの数
実行の順序
ハンドラ チェーン内で SOAP メッセージ ハンドラをグループ化します。ハンドラ チェーン内の各ハンドラには、着信メッセージと発信メッセージ両方のメソッドを定義できます。
ただし、着信メッセージと発信メッセージで同じタイプの処理が必要となるため、通常は各 SOAP メッセージ ハンドラにリクエスト SOAP メッセージと応答 SOAP メッセージを処理する別個のメソッドを定義します。一方、SOAP リクエストのみを処理し、それと同等の応答処理は行わないハンドラを設計することもできます。また、ハンドラ チェーン内の次のハンドラを呼び出さず、そのまま、任意の時点でクライアント アプリケーションに応答を送信することも可能です。
Web サービスを呼び出すときに、WebLogic Server は次のようにハンドラを実行します。
ハンドラ チェーン内のハンドラの inbound メソッドはすべて、JWS アノテーションで指定されている順序で実行されます。これらの inbound メソッドのいずれもが、SOAP のリクエスト メッセージを変更できます。
ハンドラ チェーン内の最後のハンドラが実行されると、WebLogic Server は、Web サービスを実装するバックエンド コンポーネントを呼び出し、最終的な SOAP のリクエスト メッセージを渡します。
バックエンド コンポーネントの実行が終了したら、ハンドラ チェーン内のハンドラの outbound メソッドが、JWS アノテーションで指定されているのとは逆の順序で実行されます。これらの outbound メソッドのいずれもが、SOAP の応答メッセージを変更できます。
ハンドラ チェーン内の最初のハンドラが実行されると、WebLogic Server は、Web サービスを呼び出したクライアント アプリケーションに最終的な SOAP 応答メッセージを返します。
たとえば、JWS ファイルで @HandlerChain
JWS アノテーションを使用して外部コンフィグレーション ファイルを指定することになっており、そのコンフィグレーション ファイルでは、次の例に示す 3 つのハンドラが格納された SimpleChain
というハンドラ チェーンを定義していると仮定します。
<?xml version="1.0" encoding="UTF-8" ?> <handler-chains xmlns="http://java.sun.com/xml/ns/javaee"> <handler-chain> <handler> <handler-class> Handler1 </handler-class> </handler> </handler-chain> <handler-chain> <handler> <handler-class> Handler2 </handler-class> </handler> </handler-chain> <handler-chain> <handler> <handler-class> Handler3 </handler-class> </handler> </handler-chain> </handler-chains>
次の図は、WebLogic Server で各ハンドラの inbound メソッドと outbound メソッドが実行される順序を示しています。
SOAP メッセージ ハンドラには 2 つのタイプがあります。次の表にそれぞれの定義を示します。
表 8-3 SOAP メッセージ ハンドラのタイプ
ハンドラ タイプ | 説明 |
---|---|
SOAP ハンドラ |
ヘッダを含めた SOAP メッセージ全体へのアクセスを可能にします。SOAP ハンドラは、 |
論理ハンドラ |
メッセージのペイロードへのアクセスを提供します。メッセージ内のプロトコル固有の情報 (たとえばヘッダ) を変更することはできません。論理ハンドラは、 ペイロードには、JAXB オブジェクトまたは |
両方のタイプのメッセージ ハンドラが拡張する javax.xml.ws.Handler
インタフェースは、次の表に示すメソッドを定義します。(http://java.sun.com/javase/6/docs/api/javax/xml/ws/handler/Handler.html
を参照)。
表 8-4 ハンドラ インタフェース メソッド
メソッド | 説明 |
---|---|
handleMessage() |
着信および発信メッセージの通常処理を管理します。 |
handleFault() |
着信および発信メッセージの障害処理を管理します。「Handler.handleFault() メソッドの実装」を参照してください。 |
close() |
メッセージ交換を完了し、処理の間にアクセスしたリソースをクリーンアップします。「Handler.close() メソッドの実装」を参照してください。 |
また、@javax.annotation.PostConstruct
および @javax.annotation.PreDestroy
アノテーションを使用すると、ハンドラが作成された後に実行するメソッドとハンドラが破棄される前に実行するメソッドを指定できます。
特に画像などの添付ファイルを処理する場合などには、ハンドラ内から直接 SOAP メッセージを表示または更新しなければならない場合もあります。この場合は、(http://java.sun.com/webservices/saaj/docs.html
) の SOAP With Attachments API for Java 1.1 (SAAJ) 仕様の構成要素である javax.xml.soap.SOAPMessage
抽象クラスを使用します。詳細については、「SAAJ を使用した SOAP リクエスト メッセージおよび応答メッセージの直接操作」を参照してください。
次に、単純な SOAP ハンドラのサンプルを示します。このハンドラは、メッセージの内容とともに、メッセージが着信か発信かを返します。
package examples.webservices.handler; import java.util.Set; import java.util.Collections; import javax.xml.namespace.QName; import javax.xml.ws.handler.soap.SOAPHandler; import javax.xml.ws.handler.MessageContext; import javax.xml.ws.handler.soap.SOAPMessageContext; import javax.xml.soap.SOAPMessage; public class Handler1 implements SOAPHandler<SOAPMessageContext> { public Set<QName> getHeaders() { return Collections.emptySet(); } public boolean handleMessage(SOAPMessageContext messageContext) { Boolean outboundProperty = (Boolean) messageContext.get (MessageContext.MESSAGE_OUTBOUND_PROPERTY); if (outboundProperty.booleanValue()) { System.out.println("\nOutbound message:"); } else { System.out.println("\nInbound message:"); } System.out.println("** Response: "+messageContext.getMessage().toString()); return true; } public boolean handleFault(SOAPMessageContext messageContext) { return true; } public void close(MessageContext messageContext) { } }
次に、単純な論理ハンドラのサンプルを示します。このハンドラは、メッセージの内容とともに、メッセージが着信か発信かを返します。
package examples.webservices.handler; import java.util.Set; import java.util.Collections; import javax.xml.namespace.QName; import javax.xml.ws.handler.LogicalHandler; import javax.xml.ws.handler.MessageContext; import javax.xml.ws.handler.LogicalMessageContext; import javax.xml.ws.LogicalMessage; import javax.xml.transform.Source; public class Handler2 implements LogicalHandler<LogicalMessageContext> { public Set<QName> getHeaders() { return Collections.emptySet(); } public boolean handleMessage(LogicalMessageContext messageContext) { Boolean outboundProperty = (Boolean) messageContext.get (MessageContext.MESSAGE_OUTBOUND_PROPERTY); if (outboundProperty.booleanValue()) { System.out.println("\nOutbound message:"); } else { System.out.println("\nInbound message:"); } System.out.println("** Response: "+messageContext.getMessage().toString()); return true; } public boolean handleFault(LogicalMessageContext messageContext) { return true; } public void close(MessageContext messageContext) { } }
Handler.handleMessage()
メソッドは、バックエンド コンポーネントによって処理される前および後に、SOAP のリクエスト メッセージをインターセプトするために呼び出されます。そのシグネチャは次のとおりです。
public boolean handleMessage(C context) throws java.lang.RuntimeException, java.xml.ws.ProtocolException {}
このメソッドを実装すると、バックエンド コンポーネントによって処理される前および後に、SOAP メッセージ内のデータの暗号化/復号化などのタスクを実行できます。
C
は、javax.xml.ws.handler.MessageContext
を拡張します。(http://java.sun.com/javase/6/docs/api/javax/xml/ws/handler/MessageContext.html
を参照)。ハンドラ チェーン内のハンドラは、MessageContext
プロパティを使用して、メッセージが着信か発信かを識別し、処理状態を共有します。MessageContext
の SOAPMessageContext
または LogicalMessageContext
サブインタフェースを使用すると、SOAP メッセージまたは論理メッセージの内容を取得したり設定したりできます。詳細については、「メッセージ コンテキスト プロパティの値とメソッドの使用」を参照してください。
SOAP メッセージのすべての処理をコーディングしたら、以下のシナリオのいずれかをコーディングします。
true
を返すことにより、ハンドラ リクエスト チェーン内の次のハンドラを呼び出す。
リクエスト チェーンの次のハンドラは、@HandlerChain
アノテーションによって指定されたコンフィグレーション ファイル内の <handler-chain>
要素の次の <handler>
下位要素として指定されます。
false
を返すことにより、ハンドラ リクエスト チェーンの処理をブロックする。
ハンドラ リクエスト チェーンの処理をブロックすると、Web サービスのこの呼び出しについては、バックエンド コンポーネントは実行されなくなります。Web サービスの一部の呼び出しの結果をキャッシュしてあり、そのリストに現在の呼び出しも含まれている場合は、この操作が便利な場合があります。
ハンドラ リクエスト チェーンの処理は中断されますが、WebLogic Server が、現在のハンドラから順に、response チェーンを呼び出します。
ハンドラに固有のすべての実行時エラーに対して、java.lang.RuntimeException
または java.xml.ws.ProtocolException
を送出する。
WebLogic Server は、この例外を捕捉すると、ハンドラ リクエスト チェーンの後続の処理を終了し、この例外を WebLogic Server のログ ファイルに記録した上で、このハンドラの handleFault()
メソッドを呼び出します。
Handler.handleFault()
メソッドは、SOAP メッセージ処理モデルに基づいて SOAP 障害を処理します。そのシグネチャは次のとおりです。
public boolean handleFault(C context) throws java.lang.RuntimeException, java.xml.ws.ProtocolException{}
このメソッドを実装すると、バックエンド コンポーネントによって生成された障害のほか、handleMessage()
メソッドによって生成されたあらゆる SOAP 障害の処理も扱うことができます。
C
は、javax.xml.ws.handler.MessageContext
を拡張します。(http://java.sun.com/javase/6/docs/api/javax/xml/ws/handler/MessageContext.html
を参照)。ハンドラ チェーン内のハンドラは、MessageContext
プロパティを使用して、メッセージが着信か発信かを識別し、処理状態を共有します。MessageContext
の LogicalMessageContext
または SOAPMessageContext
サブインタフェースを使用すると、SOAP メッセージまたは論理メッセージの内容を取得したり設定したりできます。詳細については、「メッセージ コンテキスト プロパティの値とメソッドの使用」を参照してください。
SOAP 障害のすべての処理をコーディングしたら、次のいずれかを実行します。
true
を返すことにより、ハンドラ チェーン内の次のハンドラの handleFault()
メソッドを呼び出す。
false
を返すことにより、ハンドラ障害チェーンの処理をブロックする。
Handler.close()
は、メッセージ交換を完了し、処理の間にアクセスしたリソースをクリーンアップします。そのシグネチャは次のとおりです。
public boolean close(MessageContext context) {}
SOAP メッセージ ハンドラには、以下のコンテキスト オブジェクトが渡されます。
表 8-5 メッセージ コンテキスト プロパティの値
メッセージ コンテキスト プロパティの値 | 説明 |
---|---|
javax.xml.ws.handler.LogicalMessageContext |
論理ハンドラのコンテキスト オブジェクト |
javax.xml.ws.handler.soap.SOAPMessageContext |
SOAP ハンドラのコンテキスト オブジェクト |
名コンテキスト オブジェクトは、javax.xml.ws.handler.MessageContext
を拡張します。これらのコンテキスト オブジェクトを使用することで、SOAP メッセージ ハンドラの実行時プロパティにクライアント アプリケーションや Web サービスからアクセスできるだけでなく、Web サービスの javax.xml.ws.WebServiceContext
から直接アクセスすることも可能になります。(https://jax-ws.dev.java.net/nonav/jax-ws-20-pfd/api/javax/xml/ws/WebServiceContext.html
を参照)。
たとえば、MessageContext.MESSAGE_OUTBOUND_PROPERTY
には、メッセージの方向を識別するために使用する Boolean
値が格納されています。リクエストの間にこのプロパティの値をチェックすることで、メッセージが着信リクエストなのか発信リクエストなのかを識別できます。このプロパティは、クライアントサイドのハンドラからアクセスしたときは true
、サーバサイドのハンドラからアクセスしたときは false
になります。
使用できる MessageContext
プロパティ値の詳細については、『Oracle Fusion Middleware JAX-WS を使用した Oracle WebLogic Server Web サービス入門』の「MessageContext プロパティ値の使用」を参照してください。
LogicalMessageContext
クラスは、論理メッセージを処理する次のメソッドを定義します。詳細については、(http://java.sun.com/javase/6/docs/api/javax/xml/ws/handler/LogicalMessageContext.html
) の java.xml.ws.handler.LogicalMessageContext
Javadoc を参照してください。
表 8-6 LogicalMessageContext クラスのメソッド
メソッド | 説明 |
---|---|
getMessage() |
SOAPメッセージを含む |
SOAPMessageContext
クラスは、SOAP メッセージを処理する以下のメソッドを定義します。詳細については、(http://java.sun.com/javase/6/docs/api/javax/xml/ws/handler/soap/SOAPMessageContext.html
) の java.xml.ws.handler.soap.SOAPMessageContext
Javadoc を参照してください。
注意 : SOAP メッセージ自体は、(http://java.sun.com/javase/6/docs/api/javax/xml/soap/SOAPMessage.html ) の javax.xml.soap.SOAPMessage オブジェクトに格納されています。このオブジェクトの詳細については、「SAAJ を使用した SOAP リクエスト メッセージおよび応答メッセージの直接操作」を参照してください。 |
javax.xml.soap.SOAPMessage
抽象クラスは、(http://java.sun.com/webservices/saaj/docs.html
) の SOAP With Attachments API for Java 1.1 (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
オブジェクトには、(http://java.sun.com/javase/6/docs/api/javax/xml/soap/AttachmentPart.html
を参照。) SOAP メッセージに対するオプションの添付ファイルが入っています。添付ファイルは、SOAP メッセージの残りの部分とは異なり、XML フォーマットの必須部分ではないので、その形式は、単純なテキストからイメージ ファイルまで、さまざまです。
注意 : SOAP メッセージ ハンドラから直接に添付ファイルjava.awt.Image にアクセスする場合は、「SOAP メッセージ ハンドラで画像添付ファイルの操作」で重要情報を参照してください。 |
添付ファイルを操作するには、SOAPMessage
クラスの以下のメソッドを使用します。詳細については、(http://java.sun.com/javase/6/docs/api/javax/xml/soap/SOAPMessage.html
) の javax.xml.soap.SOAPMessage
Javadoc を参照してください。
表 8-8 添付ファイルの操作に使用する SOAPMessage クラスのメソッド
メソッド | 説明 |
---|---|
addAttachmentPart() |
作成された |
countAttachments() |
この SOAP メッセージに含まれている添付ファイルの数を返します。 |
createAttachmentPart() |
他のタイプの |
getAttachments() |
すべての添付ファイルを |
この節では、添付ファイル 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 メッセージ ハンドラでは、このデータ ストリームをデシリアライズして元の画像を作成し直す必要があるということです。
@javax.jws. HandlerChain
アノテーションが (この章では、簡略化のために@HandlerChain
とも言います) を使用すると、Web サービスのハンドラ チェーンをコンフィグレーションできます。file
属性を使用して、Web サービスと関連付けるハンドラ チェーンのコンフィグレーションが含まれた外部ファイルを指定します。コンフィグレーションには、チェーン内のハンドラのリスト、ハンドラが実行される順序、初期化パラメータなどが含まれます。
次の JWS ファイルでは、@HandlerChain
アノテーションの使用例を示します。関連の Java コードは太字で示しています。
package examples.webservices.handler; import javax.jws.WebMethod; import javax.jws.WebService; import javax.jws.HandlerChain; import javax.annotation.Resource; import javax.xml.ws.WebServiceContext; @WebService(name = "Handler", targetNamespace = "http://example.org") @HandlerChain(file="handler-chain.xml") public class HandlerWS { @Resource WebServiceContext ctx; @WebMethod() public String getProperty(String propertyName) { return (String) ctx.getMessageContext().get(propertyName); } }
このサンプルに示すように、@HandlerChain
アノテーションを使用する前に、それを JWS ファイルにインポートする必要があります。
@HandlerChain
アノテーションの file
属性を使用し、ハンドラ チェーンのコンフィグレーション情報を含む外部ファイルの名前を指定します。この属性の値は URL です。これは相対でも絶対でもかまいません。相対 URL は、ファイルをコンパイルするために jwsc
Ant タスクを実行した時点での JWS ファイルの場所を基準とします。
注意 : 1 つの JWS ファイル内に複数の@HandlerChain アノテーションを指定すると、エラーになります。 |
外部コンフィグレーション ファイル作成の詳細については、「ハンドラ チェーン コンフィグレーション ファイルの作成」を参照してください。
この節で説明した標準的な JWS アノテーションの詳細については、http://www.jcp.org/en/jsr/detail?id=181
にある Web Services Metadata for the Java Platform 仕様を参照してください。
前の節で説明したように、Web サービスにハンドラ チェーンを関連付けるには、JWS ファイル内で @HandlerChain
アノテーションを使用します。その際には、外部コンフィグレーション ファイルからなるハンドラ チェーン ファイルを作成し、ハンドラ チェーン内のハンドラのリスト、ハンドラの実行順序、初期化パラメータなどを指定する必要があります。
このファイルは、JWS ファイルの外部にあるため、この単一のコンフィグレーション ファイルを複数の Web サービスで使用するようにコンフィグレーションし、エンタープライズ内のすべての Web サービスに関してハンドラ コンフィグレーション ファイルを標準化できます。加えて、すべての Web サービスを再コンパイルすることなく、ハンドラ チェーンのコンフィグレーションを変更できます。
コンフィグレーション ファイルは、次の簡単なサンプルに示すように、XML を使用して 1 つまたは複数のハンドラ チェーンをリストします。
<?xml version="1.0" encoding="UTF-8"?> <handler-chains xmlns="http://java.sun.com/xml/ns/javaee"> <handler-chain> <handler> <handler-class>examples.webservices.handler.Handler1</handler-class> </handler> </handler-chain> <handler-chain> <handler> <handler-class>examples.webservices.handler.Handler2</handler-class> </handler> </handler-chain> </handler-chains>
このサンプルでは、2 つのハンドラが <handler-class>
要素で指定したクラス名でハンドラ チェーンに実装されています。2 つのハンドラは、関の Web サービス オペレーションの前には昇順で実行され、オペレーション実行後には逆順で実行されます。
ハンドラによって実装されるハンドラ初期化パラメータおよび SOAP ロールを指定するには、それぞれ <handler>
要素の <init-param>
および <soap-role>
子要素を使用します。
同じハンドラ チェーンに、論理ハンドラと SOAP ハンドラを含めることができます。ハンドラ チェーンは実行時に再び並べ替えられ、発信メッセージではすべての論理ハンドラが SOAP ハンドラより前に実行され、着信メッセージではすべての SOAP ハンドラが論理ハンドラより前に実行されます。
外部コンフィグレーション ファイルを定義する XML スキーマ、その作成に関する詳細、およびさらなるサンプルについては、http://www.jcp.org/en/jsr/detail?id=181
にある Web Services Metadata for the Java Platform 仕様を参照してください。
この節では、Web サービスをコンパイルおよびビルドする作業用の build.xml
Ant ファイルがあり、ハンドラ チェーンが含まれるように、そのビルド ファイルを更新することを想定しています。この build.xml
ファイルの作成については、『Oracle Fusion Middleware JAX-WS を使用した Oracle WebLogic Server Web サービス入門』の「WebLogic Web サービスの開発」を参照してください。
メッセージ ハンドラのコンパイルとビルドが含まれるように開発環境を更新するには、以下のガイドラインに従います。
JWS ファイルに @HandlerChain
アノテーションを追加したら、jwsc
Ant タスクを再実行して JWS ファイルを再コンパイルし、新しい Web サービスを生成する必要がある。これは、JWS ファイル内のアノテーションに変更を加えた場合は常に当てはまります。
JWS ファイルで @HandlerChain
アノテーションを使用し、jwsc
Ant タスクを再実行して Web サービスを再生成し、その後、外部コンフィグレーション ファイルだけを変更した場合は、2 度目の変更を有効にするために jwsc
を再実行する必要はありません。
以下の条件がすべて満たされていれば、jwsc
Ant タスクは SOAP メッセージ ハンドラ Java ファイルをハンドラ クラスにコンパイル (およびその後それらを生成されたアプリケーションにパッケージ化) する。
ハンドラ クラスは JWS ファイルの @HandlerChain
アノテーションにおいて参照される。
Java ファイルは sourcepath
属性で指定されたディレクトリ内に置かれる。
クラスは現在 CLASSPATH 内に存在しない。
ハンドラ クラスを jwsc
で自動的にコンパイルするのではなく、ユーザ側でコンパイルする場合は、jwsc
Ant タスクを実行する前に、コンパイルされたクラスが CLASSPATH 内にあることを確認してください。
ハンドラ チェーンが関連付けられている Web サービスのデプロイおよび呼び出しは、ハンドラ チェーンのない Web サービスのデプロイおよび呼び出しと同様に行う。唯一の相違点は、Web サービスのどのオペレーションを呼び出す場合でも、WebLogic Web サービスのランタイムは、オペレーション呼び出しの前と後の両方で、ハンドラ チェーン内のハンドラを実行するということです。
クライアントサイド SOAP メッセージ ハンドラは、以下のいずれかの方法で定義できます。
ポート ポリシーや javax.xml.ws.Dispatch
オブジェクトのように、ハンドラ チェーンを直接 javax.xml.ws.BindingProvider
に設定します。たとえば、
package examples.webservices.handler.client; import javax.xml.namespace.QName; import java.net.MalformedURLException; import java.net.URL; import javax.xml.ws.handler.Handler; import javax.xml.ws.Binding; import javax.xml.ws.BindingProvider; import java.util.List; import examples.webservices.handler.Handler1; import examples.webservices.handler.Handler2; public class Main { public static void main(String[] args) { HandlerWS test; try { test = new HandlerWS(new URL(args[0] + "?WSDL"), new QName("http://example.org", "HandlerWS") ); } catch (MalformedURLException murl) { throw new RuntimeException(murl); } HandlerWSPortType port = test.getHandlerWSPortTypePort(); Binding binding = ((BindingProvider)port).getBinding(); List<Handler> handlerList = binding.getHandlerChain(); handlerList.add(new Handler1()); handlerList.add(new Handler2()); binding.setHandlerChain(handlerList); String result = null; result = port.sayHello("foo bar"); System.out.println( "Got result: " + result ); } }
Service
インスタンスに javax.xml.ws.handler.HandlerResolver
を実装します。たとえば、
public static class MyHandlerResolver implements HandlerResolver { public List<Handler> getHandlerChain(PortInfo portInfo) { List<Handler> handlers = new ArrayList<Handler>(); // 情報に基づいてリストにハンドラを追加する return handlers; } }
setHandlerResolver()
メソッドを使用して、Service
インスタンスにハンドラ解決メカニズムを追加します。この場合は、Service
インスタンスから作成されたポート プロキシまたは Dispatch
オブジェクトで、HandlerResolver
を使用してハンドラ チェーンを特定します。次に例を示します。
test.setHandlerResolver(new MyHandlerResolver());
ハンドラ チェーンの記述を格納する <binding>
要素を含むカスタマイズ ファイルを作成する。<handler-chains>
要素のスキーマは、ハンドラ チェーン ファイル (サーバ上) とカスタマイズ ファイルで同じものを使用します。次に例を示します。
<bindings xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" wsdlLocation="http://localhost:7001/handler/HandlerWS?WSDL" xmlns="http://java.sun.com/xml/ns/jaxws"> <bindings node="wsdl:definitions" xmlns:jws="http://java.sun.com/xml/ns/javaee"> <handler-chains> <handler-chain> <handler> <handler-class>examples.webservices.handler.Handler1 </handler-class> </handler> </handler-chain> <handler-chain> <handler> <handler-class>examples.webservices.handler.Handler2 </handler-class> </handler> </handler-chain> </handler-chains> </bindings>
clientgen
コマンドの <binding>
子要素を使用してカスタマイズ ファイルに渡します。