| Oracle® Fusion Middleware Oracle WebLogic Server JAX-WS Webサービスの高度な機能のプログラミング 11g リリース1(10.3.4) B61633-02 |
|
![]() 前 |
![]() 次 |
以下の節では、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ファイルがあることも前提となっています。詳細は、『Oracle WebLogic Server JAX-WS Webサービス・スタート・ガイド』を参照してください。
使用例とサンプル
WebLogic Webサービスの開発
JWSファイルのプログラミング
Webサービスの呼出し
表15-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 WebLogic Server JAX-WS Webサービス・スタート・ガイド』のスタンドアロン・クライアントからのWebサービスの呼出し: 主な手順に関する項を参照してください。
表15-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つのタイプがあります。次の表にそれぞれの定義を示します。
表15-3 SOAPメッセージ・ハンドラのタイプ
| ハンドラ・タイプ | 説明 |
|---|---|
|
SOAPハンドラ |
ヘッダーを含めたSOAPメッセージ全体へのアクセスを可能にします。SOAPハンドラは、 |
|
論理ハンドラ |
メッセージのペイロードへのアクセスを提供します。メッセージ内のプロトコル固有の情報(たとえばヘッダー)を変更することはできません。論理ハンドラは、 ペイロードには、JAXBオブジェクトまたは |
両方のタイプのメッセージ・ハンドラが拡張するjavax.xml.ws.Handlerインタフェースは、次の表に示すメソッドを定義します。(http://download.oracle.com/javaee/5/api/javax/xml/ws/handler/Handler.htmlを参照)。
表15-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://download.oracle.com/javaee/5/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://download.oracle.com/javaee/5/api/javax/xml/ws/handler/MessageContext.htmlを参照)。ハンドラ・チェーン内のハンドラは、MessageContextプロパティを使用して、メッセージが着信か発信かを識別し、処理状態を共有します。MessageContextのLogicalMessageContextまたはSOAPMessageContextサブインタフェースを使用すると、SOAPメッセージまたは論理メッセージの内容を取得したり設定したりできます。詳細は、「メッセージ・コンテキスト・プロパティの値とメソッドの使用」を参照してください。
SOAP障害のすべての処理をコーディングしたら、次のいずれかを実行します。
trueを返すことにより、ハンドラ・チェーン内の次のハンドラのhandleFault()メソッドを呼び出します。
falseを返すことにより、ハンドラ障害チェーンの処理をブロックします。
Handler.close()は、メッセージ交換を完了し、処理の間にアクセスしたリソースをクリーンアップします。そのシグネチャは次のとおりです。
public boolean close(MessageContext context) {}
SOAPメッセージ・ハンドラには、以下のコンテキスト・オブジェクトが渡されます。
表15-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 WebLogic Server JAX-WS Webサービス・スタート・ガイド』のMessageContextプロパティ値の使用に関する項を参照してください。
LogicalMessageContextクラスは、論理メッセージを処理する次のメソッドを定義します。詳細は、(http://download.oracle.com/javaee/5/api/javax/xml/ws/handler/LogicalMessageContext.html)のjava.xml.ws.handler.LogicalMessageContext Javadocを参照してください。
表15-6 LogicalMessageContextクラスのメソッド
| メソッド | 説明 |
|---|---|
getMessage() |
SOAPメッセージを含む |
SOAPMessageContextクラスは、SOAPメッセージを処理する次のメソッドを定義します。詳細は、(http://download.oracle.com/javaee/5/api/javax/xml/ws/handler/soap/SOAPMessageContext.html)のjava.xml.ws.handler.soap.SOAPMessageContext Javadocを参照してください。
|
注意: SOAPメッセージ自体は、(http://download.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://download.oracle.com/javaee/5/api/javax/xml/soap/AttachmentPart.htmlを参照)には、 SOAPメッセージに対するオプションの添付ファイルが入っています。添付ファイルは、SOAPメッセージの残りの部分とは異なり、XMLフォーマットの必須部分ではないので、その形式は、単純なテキストからイメージ・ファイルまで、様々です。
添付ファイルを操作するには、SOAPMessageクラスの次のメソッドを使用します。詳細には、(http://download.oracle.com/javaee/5/api/javax/xml/soap/SOAPMessage.html)のjavax.xml.soap.SOAPMessage Javadocを参照してください。
表15-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ファイルの作成については、『Oracle WebLogic Server JAX-WS 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>();
// 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>子要素を使用してカスタマイズ・ファイルに渡します。