Oracle® Fusion Middleware Oracle WebLogic Server 12.1.3 JAX-WS Webサービスの開発 12c (12.1.3) E57563-04 |
|
![]() 前 |
![]() 次 |
この章では、Java API for XML Web Services (JAX-WS)を使用したWebLogic Server 12.1.3用のWebLogic WebサービスでSOAPメッセージ・ハンドラを作成および使用する方法について説明します。
この章の内容は次のとおりです:
Webサービスおよびそのクライアントは、メッセージのリクエストやレスポンスの追加処理において、SOAPメッセージにアクセスする必要が生じることがあります。SOAPメッセージ・ハンドラは、Webサービスのリクエストとレスポンスの両方で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
ファイルがあることも前提となっています。詳細については、以下を参照してください。
表18-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
ファイルがあることが前提となっています。詳細は、「Java SEクライアントからのWebサービスの呼出し」を参照してください。
表18-2 Webサービス・クライアントに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つのタイプがあります。次の表にそれぞれの定義を示します。
表18-3 SOAPメッセージ・ハンドラのタイプ
ハンドラ・タイプ | 説明 |
---|---|
SOAPハンドラ |
ヘッダーを含めたSOAPメッセージ全体へのアクセスを可能にします。SOAPハンドラは、 |
論理ハンドラ |
メッセージのペイロードへのアクセスを提供します。メッセージ内のプロトコル固有の情報(たとえばヘッダー)を変更することはできません。論理ハンドラは、 ペイロードには、JAXBオブジェクトまたは |
両方のタイプのメッセージ・ハンドラが拡張するjavax.xml.ws.Handler
インタフェースは、次の表に示すメソッドを定義します。(http://docs.oracle.com/javaee/6/api/javax/xml/ws/handler/Handler.html
を参照)。
表18-4 ハンドラ・インタフェース・メソッド
メソッド | 説明 |
---|---|
handleMessage() |
インバウンドおよびアウトバウンド・メッセージの通常処理を管理します。 |
handleFault() |
インバウンドおよびアウトバウンド・メッセージのフォルト処理を管理します。「Handler.handleFault()メソッドの実装」を参照してください。 |
close() |
メッセージ交換を完了し、処理の間にアクセスしたリソースをクリーンアップします。「Handler.close()メソッドの実装」を参照してください。 |
また、@javax.annotation.PostConstruct
および@javax.annotation.PreDestroy
アノテーションを使用すると、ハンドラが作成された後に実行するメソッドとハンドラが破棄される前に実行するメソッドを指定できます。
特に画像などの添付ファイルを処理する場合などには、ハンドラ内から直接SOAPメッセージを表示または更新しなければならない場合もあります。この場合は、http://java.net/projects/saaj/
の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://docs.oracle.com/javaee/6/api/javax/xml/ws/handler/MessageContext.html
を参照)。ハンドラ・チェーン内のハンドラは、MessageContext
プロパティを使用して、メッセージがインバウンドかアウトバウンドかを識別し、処理状態を共有します。MessageContext
のSOAPMessageContext
またはLogicalMessageContext
サブインタフェースを使用すると、SOAPメッセージまたは論理メッセージの内容を取得したり設定したりできます。詳細については、「メッセージ・コンテキスト・プロパティの値とメソッドの使用」を参照してください。
SOAPメッセージのすべての処理をコーディングしたら、以下のシナリオのいずれかをコーディングします。
true
を返すことにより、ハンドラ・リクエスト・チェーン内の次のハンドラを呼び出します。
リクエスト・チェーンの次のハンドラは、@HandlerChain
アノテーションによって指定された構成ファイル内の<handler-chain>
要素の次の<handler>
下位要素として指定されます。
false
を返すことにより、ハンドラ・リクエスト・チェーンの処理をブロックします。
ハンドラ・リクエスト・チェーンの処理をブロックすると、Webサービスのこの呼出しについては、バックエンド・コンポーネントは実行されなくなります。Webサービスの一部の呼出しの結果をキャッシュしてあり、そのリストに現在の呼出しも含まれている場合は、この操作が便利な場合があります。
ハンドラ・リクエスト・チェーンの処理は中断されますが、WebLogic Serverが、現在のハンドラから順に、レスポンス・チェーンを呼び出します。
ハンドラに固有のすべての実行時エラーに対して、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://docs.oracle.com/javaee/6/api/javax/xml/ws/handler/MessageContext.html
を参照)。ハンドラ・チェーン内のハンドラは、MessageContext
プロパティを使用して、メッセージがインバウンドかアウトバウンドかを識別し、処理状態を共有します。MessageContext
のLogicalMessageContext
またはSOAPMessageContext
サブインタフェースを使用すると、SOAPメッセージまたは論理メッセージの内容を取得したり設定したりできます。詳細については、「メッセージ・コンテキスト・プロパティの値とメソッドの使用」を参照してください。
SOAPフォルトのすべての処理をコーディングしたら、次のいずれかを実行します。
true
を返すことにより、ハンドラ・チェーン内の次のハンドラのhandleFault()
メソッドを呼び出します。
false
を返すことにより、ハンドラ・フォルト・チェーンの処理をブロックします。
Handler.close()
は、メッセージ交換を完了し、処理の間にアクセスしたリソースをクリーンアップします。そのシグネチャは次のとおりです。
public boolean close(MessageContext context) {}
SOAPメッセージ・ハンドラには、以下のコンテキスト・オブジェクトが渡されます。
表18-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.java.net/nonav/jax-ws-20-pfd/api/javax/xml/ws/WebServiceContext.html
を参照)。
たとえば、MessageContext.MESSAGE_OUTBOUND_PROPERTY
には、メッセージの方向を識別するために使用するBoolean
値が格納されています。リクエストの間にこのプロパティの値をチェックすることで、メッセージがインバウンド・リクエストなのかアウトバウンド・リクエストなのかを識別できます。このプロパティは、クライアント側のハンドラからアクセスしたときはtrue
、サーバー側のハンドラからアクセスしたときはfalse
になります。
使用可能なMessageContext
プロパティ値の詳細は、「MessageContextプロパティ値の使用」を参照してください。
LogicalMessageContext
クラスは、論理メッセージを処理する次のメソッドを定義します。詳細は、Javadocの「java.xml.ws.handler.LogicalMessageContext
」(http://docs.oracle.com/javaee/6/api/javax/xml/ws/handler/LogicalMessageContext.html
)を参照してください。
表18-6 LogicalMessageContextクラスのメソッド
メソッド | 説明 |
---|---|
getMessage() |
SOAPメッセージを含む |
SOAPMessageContext
クラスは、SOAPメッセージを処理する次のメソッドを定義します。詳細は、Javadocの「java.xml.ws.handler.soap.SOAPMessageContext
」(http://docs.oracle.com/javaee/6/api/javax/xml/ws/handler/soap/SOAPMessageContext.html
)を参照してください。
注意: SOAPメッセージ自体は、( http://docs.oracle.com/javaee/5/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 オブジェクトのsetContent メソッドおよびgetContent メソッドは、javax.xml.transform.stream.StreamSource コンテンツのみをサポートします。これらのメソッドではjavax.xml.transform.dom.DOMSource コンテンツはサポートされません。 |
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://docs.oracle.com/javaee/5/api/javax/xml/soap/AttachmentPart.html
を参照)には、SOAPメッセージに対するオプションの添付ファイルが入っています。添付ファイルは、SOAPメッセージの残りの部分とは異なり、XMLフォーマットの必須部分ではないので、その形式は、単純なテキストからイメージ・ファイルまで、様々です。
添付ファイルを操作するには、SOAPMessage
クラスの次のメソッドを使用します。詳細は、Javadocの「javax.xml.soap.SOAPMessage
」(http://docs.oracle.com/javaee/5/api/javax/xml/soap/SOAPMessage.html
)を参照してください。
表18-8 添付ファイルの操作に使用するSOAPMessageクラスのメソッド
メソッド | 説明 |
---|---|
addAttachmentPart() |
作成された |
countAttachments() |
このSOAPメッセージに含まれている添付ファイルの数を返します。 |
createAttachmentPart() |
他のタイプの |
getAttachments() |
すべての添付ファイルを |
この項では、添付ファイルjava.awt.Image
にアクセスするSOAPメッセージ・ハンドラを作成すること、およびclientgen
Antタスクによって生成されたクライアントJAX-WSポートを使用するクライアント・アプリケーションから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アノテーションの詳細は、Web Services Metadata for the Java Platform仕様(http://www.jcp.org/en/jsr/detail?id=181
)を参照してください。
前の項で説明したように、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スキーマ、その作成の詳細、および他のサンプルについては、Web Services Metadata for the Java Platform仕様(http://www.jcp.org/en/jsr/detail?id=181
)を参照してください。
この項では、Webサービスをコンパイルおよびビルドする作業用のbuild.xml
Antファイルがあり、そのビルド・ファイルを更新してハンドラ・チェーンを含めることを想定しています。このbuild.xmlファイルの作成については、「JAX-WS 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>(); // add handlers to list based on PortInfo information 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>
子要素を使用してカスタマイズ・ファイルに渡します。