ナビゲーションをスキップ

WebLogic Web サービス プログラマーズ ガイド

  前 次 前/次ボタンと目次ボタンとの区切り線 目次  

SOAP メッセージをインターセプトする SOAP メッセージ ハンドラの作成

この章では、WebLogic Web サービスの開発中に、SOAP メッセージ ハンドラを使用して SOAP のリクエスト メッセージおよび応答メッセージをインターセプトする方法について説明します。

 


SOAP メッセージ ハンドラおよびハンドラ チェーンの概要

SOAP メッセージ ハンドラは、Web サービスのリクエストと応答の両方で SOAP メッセージをインターセプトします。ハンドラは、Web サービスそのものと Web サービスを呼び出すクライアント アプリケーションの両方で作成することができます。ハンドラをどのような場合に使用するかについては、「SOAP メッセージをインターセプトする SOAP メッセージ ハンドラの使用」を参照してください。

次の表は、javax.xml.rpc.handler API の主なクラスおよびインタフェースの説明です。それらを使用してハンドラを作成する方法については、この章で後述します。

表 12-1 JAX-RPC ハンドラのインタフェースとクラス

javax.xml.rpc. ハンドラのクラスとインタフェース

説明

Handler

ハンドラ作成時に実装する主なインタフェース。SOAP のリクエスト、応答、および障害を処理するメソッドが格納されている。

HandlerInfo

web-services.xml ファイルで指定されている初期化パラメータをはじめとする、ハンドラについての情報が格納されている。

MessageContext

ハンドラによって処理されたメッセージのコンテキストを抽出する。MessageContext プロパティにより、ハンドラ チェーン内のハンドラは処理ステートを共有できる。

soap.SOAPMessageContext

SOAP メッセージの取得または更新に使用される MessageContext インタフェースのサブインタフェース。

javax.xml.soap.SOAPMessage

実際の SOAP のリクエスト メッセージまたは応答メッセージが入ったオブジェクト。ヘッダ、本文、添付ファイルが含まれる。

 


SOAP メッセージ ハンドラの作成 : 主な手順

次の手順は、servicegen Ant タスクを使用して WebLogic Web サービスをすでに実装およびアセンブルしていて、かつハンドラおよびハンドラ チェーンを追加して Web サービスを更新することを前提としています。

  1. ハンドラとハンドラ チェーンを設計します。「SOAP メッセージ ハンドラおよびハンドラ チェーンの設計」を参照してください。
  2. ハンドラ チェーン内の各ハンドラについて、javax.xml.rpc.handler.Handler インタフェースを実装する Java クラスを作成します。「ハンドラ インタフェースの実装」を参照してください。
  3. WebLogic Server には、ハンドラ クラスのコーディングの簡素化に役立つ、JAX-RPC ハンドラ API の拡張クラスが組み込まれています。weblogic.webservice.GenericHandler という抽象クラスです。「GenericHandler Abstract クラスの拡張」を参照してください。

  4. この Java コードをクラス ファイルにコンパイルします。
  5. 次の例に示すように、servicegen Ant タスクの呼び出しを含む build.xml ファイルを更新し、Web サービスをビルドする <service> 要素に <handlerChain> 子要素を追加します。
      <servicegen
destEar="ears/myWebService.ear"
warName="myWAR.war"
contextURI="web_services" >
<service
ejbJar="jars/myEJB.jar"
targetNamespace="http://www.bea.com/examples/Trader"
serviceName="TraderService"
serviceURI="/TraderService"
generateTypes="True"
expandMethods="True" >
<handlerChain
name="myChain"
handlers="myHandlers.handlerOne,
myHandlers.handlerTwo,
myHandlers.handlerThree"
/>
</service>
</servicegen>

<handlerChain> 要素の属性の詳細については、「servicegen」を参照してください。

注意 :この build.xml ファイルを使用して Web サービスを再生成すると、すべてのオペレーションがハンドラ チェーンと関連付けられます。また、servicegen を使用してハンドラに入力パラメータを指定する方法はありません。あるオペレーションのみをこのハンドラ チェーンと関連付けたい、または servicegen を使用して Web サービスを再生成したくない場合は、WebLogic Web サービスの web-services.xml ファイルを手動で更新できます。詳細については、「SOAP メッセージ ハンドラ情報による web-services.xml ファイルの更新」を参照してください。

  1. servicegen Ant タスクを再実行して Web サービスを再生成します。

クライアントサイド SOAP メッセージ ハンドラおよびハンドラ チェーンの詳細については、「クライアント アプリケーションでの SOAP メッセージ ハンドラとハンドラ チェーンの使い方」を参照してください。

 


SOAP メッセージ ハンドラおよびハンドラ チェーンの設計

SOAP メッセージ ハンドラを設計するときには、以下の事項を決める必要があります。

ハンドラ チェーン内の各ハンドラには、SOAP のリクエスト メッセージを処理するメソッドと SOAP の応答メッセージを処理するメソッドが 1 つずつあります。これらのハンドラは、web-services.xml デプロイメント記述子ファイルで指定します。順序付けされたハンドラのグループが、ハンドラ チェーンです。

Web サービスを呼び出すときに、WebLogic Server は次のようにハンドラを実行します。

  1. ハンドラ チェーン内のハンドラの handleRequest() メソッドはすべて、web-services.xml ファイルで指定されている順序で実行されます。これらの handleRequest() メソッドのいずれもが、SOAP のリクエスト メッセージを変更できます。
  2. ハンドラ チェーン内の最後のハンドラの handleRequest() メソッドが実行されると、WebLogic Server は、Web サービスを実装するバックエンド コンポーネントを呼び出し、最終的な SOAP のリクエスト メッセージを渡します。
  3. 注意 :この操作は、この Web サービスに対してバックエンド コンポーネントが実際に定義されている場合にのみ発生します。ハンドラ チェーンのみで構成される Web サービスを開発することもできます。

  4. バックエンド コンポーネントの実行が終了したら、ハンドラ チェーン内のハンドラの handleResponse() メソッドが、web-services.xml ファイルで指定されているのとは逆の順序で実行されます。これらの handleResponse() メソッドのいずれもが、SOAP の応答メッセージを変更できます。
  5. ハンドラ チェーン内の最初のハンドラの handleResponse() メソッドが実行されると、WebLogic Server は、Web サービスを呼び出したクライアント アプリケーションに最終的な SOAP 応答メッセージを返します。

たとえば、次の例のように、web-services.xml デプロイメント記述子で 3 つのハンドラが指定されている、myChain というハンドラ チェーンを指定したとします。

<handler-chains>
<handler-chain name="myChain">
<handler class-name="myHandlers.handlerOne" />
<handler class-name="myHandlers.handlerTwo" />
<handler class-name="myHandlers.handlerThree" />
</handler-chain>
</handler-chains>

次の図は、WebLogic Server で各ハンドラの handleRequest() メソッドと handleResponse() メソッドが実行される順序を示しています。

図 12-1 ハンドラ メソッドの実行順序

ハンドラ メソッドの実行順序


 

通常、SOAP のリクエスト メッセージと応答メッセージの両方で同じタイプの処理が必要となるので、各 SOAP メッセージ ハンドラには、それぞれを処理する別個のメソッドがあります。たとえば、SOAP リクエストにあるセキュア データを復号化する handleRequest() メソッドと、SOAP 応答を暗号化する handleResponse() メソッドを持つ暗号化ハンドラを設計する場合があります。

一方、SOAP リクエストのみを処理し、それと同等の応答処理は行わないハンドラを設計することもできます。

また、ハンドラ チェーン内の次のハンドラを呼び出さず、そのまま、任意の時点でクライアント アプリケーションに応答を送信することも可能です。その方法は、以下の節で説明します。

最後に、ハンドラ チェーンにハンドラのみが存在し、バックエンド コンポーネントは 1 つも存在しない Web サービスを設計することができます。この場合、最後のハンドラにある handleRequest() メソッドが実行されると、handleResponse() メソッドが自動的に呼び出されます。web-services.xml ファイルを使用して、バックエンド コンポーネントは指定せず、ハンドラのみで Web サービスを実装するように指定する例については、「SOAP メッセージ ハンドラ情報による web-services.xml ファイルの更新」を参照してください。

 


ハンドラ インタフェースの実装

SOAP メッセージ ハンドラ クラスは、この節の最後の例に示すように、javax.rpc.xml.handler.Handler インタフェースを実装する必要があります。特に、Handler インタフェースには実装する必要のある以下のメソッドが含まれています。

特に画像などの添付ファイルを処理する場合などには、ハンドラ内から直接 SOAP メッセージを表示または更新しなければならない場合もあります。その場合には、javax.xml.soap.SOAPMessage 抽象クラスを使用します。このクラスは、SOAP With Attachments API for Java 1.1 (SAAJ) 仕様の構成要素です。詳細については、「SAAJ を使用した SOAP リクエスト メッセージおよび応答メッセージの直接操作」を参照してください。

次の例は、SOAP のリクエストおよび応答メッセージを出力する簡単な SOAP メッセージ ハンドラを示しています。

package examples.webservices.handler.log;
import java.util.Map;
import javax.xml.rpc.handler.Handler;
import javax.xml.rpc.handler.HandlerInfo;
import javax.xml.rpc.handler.MessageContext;
import javax.xml.rpc.handler.soap.SOAPMessageContext;
import javax.xml.rpc.JAXRPCException;
import javax.xml.namespace.QName;
import weblogic.logging.NonCatalogLogger;
/**
* SOAP のリクエストおよび応答メッセージにアクセスするために使用する、ハンドラ チェーンのハンドラを
* 実装するクラス
* <p>
* このクラスは、<code>javax.xml.rpc.handler.Handler</code> インタフェースを
* 実装するものであり、 単純に SOAP のリクエスト メッセージおよび応答メッセージが
* バックエンド コンポーネントによって処理される前に、ログ ファイルに出力する
*
* @author Copyright (c) 2003 by BEA Systems. All Rights Reserved.
*/
public final class LogHandler
implements Handler
{
private NonCatalogLogger log;
  private HandlerInfo handlerInfo;
  /**
* ハンドラのインスタンスを初期化する。 メッセージ ログの記録先となる
* nonCatalogLogger を作成する
*/
public void init(HandlerInfo hi) {
log = new NonCatalogLogger("WebService-LogHandler");
handlerInfo = hi;
}
  /**
* ハンドラのインスタンスを破棄する
*/
public void destroy() {}
  public QName[] getHeaders() { return handlerInfo.getHeaders(); }
  /**
* Java クラスのバックエンド コンポーネントに SOAP リクエスト メッセージが送信される前に、
* そのメッセージがログ ファイルに記録されることを指定する
*/
public boolean handleRequest(MessageContext mc) {
SOAPMessageContext messageContext = (SOAPMessageContext) mc;
    System.out.println("** Request: "+messageContext.getMessage().toString());
log.info(messageContext.getMessage().toString());
return true;
}
  /**
* Web サービスを呼び出したクライアント アプリケーションに SOAP 応答メッセージが
* 送り返される前に、そのメッセージがログ ファイルに記録されることを指定する
*/
public boolean handleResponse(MessageContext mc) {
    SOAPMessageContext messageContext = (SOAPMessageContext) mc;
    System.out.println("** Response: "+messageContext.getMessage().toString());
log.info(messageContext.getMessage().toString());
return true;
}
  /**
* SOAP 障害が Handler インスタンスによって送出された場合、メッセージが
* ログ ファイルに記録されることを指定する
*/
public boolean handleFault(MessageContext mc) {
SOAPMessageContext messageContext = (SOAPMessageContext) mc;
    System.out.println("** Fault: "+messageContext.getMessage().toString());
log.info(messageContext.getMessage().toString());
return true;
}

Handler.init() メソッドを実装する

Handler.init() メソッドは、Handler オブジェクトのインスタンスを作成し、そのインスタンスが自動的に初期化されるようにするために呼び出されます。そのシグネチャは次のとおりです。

  public void init(HandlerInfo config) throws JAXRPCException {}

HandlerInfo オブジェクトには、web-services.xml ファイルで指定されている初期化パラメータをはじめとする、SOAP メッセージ ハンドラについての情報が格納されています。HandlerInfo.getHandlerConfig() メソッドを使用してパラメータを取得すると、このメソッドは、名前と値の組み合わせの入った Map オブジェクトを返します。

初期化パラメータを処理する必要がある場合、または、他の初期化タスクを実行する必要がある場合は、init() メソッドを実装します。

初期化パラメータの使用例としては、デバッグのオン、オフ、メッセージやエラーを書き込むためのログ ファイルの名前の指定などがあります。

Handler.destroy() メソッドを実装する

Handler.destroy() メソッドは、Handler オブジェクトのインスタンスを破棄するために呼び出されます。そのシグネチャは次のとおりです。

  public void destroy() throws JAXRPCException {}

destroy() メソッドを実装すると、ハンドラのライフサイクルを通じて取得されたあらゆるリソースを解放できます。

Handler.getHeaders() メソッドを実装する

Handler.getHeaders() メソッドは、このハンドラ インスタンスで処理されたヘッダ ブロックを取得します。そのシグネチャは次のとおりです。

  public QName[] getHeaders() {}

Handler.handleRequest() メソッドを実装する

Handler.handleRequest() メソッドは、バックエンド コンポーネントによって処理される前に SOAP のリクエスト メッセージをインターセプトするために呼び出されます。そのシグネチャは次のとおりです。

  public boolean handleRequest(MessageContext mc) throws JAXRPCException  {}

このメソッドを実装して、バックエンド コンポーネントによって処理される前に SOAP メッセージにあるデータを復号化し、リクエストに含まれているパラメータの数が正しいかどうかなどの確認ができます。

MessageContext オブジェクトは、SOAP メッセージ ハンドラによって処理されたメッセージのコンテキストを抽出します。MessageContext プロパティにより、ハンドラ チェーン内のハンドラは処理ステートを共有できます。

MessageContextSOAPMessageContext サブインタフェースを使用すると、SOAP のリクエスト メッセージの内容を取得または更新することができます。SOAP のリクエスト メッセージそのものは、javax.xml.soap.SOAPMessage オブジェクトに格納されます。このオブジェクトの詳細については、「SAAJ を使用した SOAP リクエスト メッセージおよび応答メッセージの直接操作」を参照してください。

SOAPMessageContext クラスは、SOAP リクエストを処理する次の 2 つのメソッドを定義します。

SOAP リクエストのすべての処理をコーディングしたら、次のいずれかを実行します。

Handler.handleResponse() メソッドを実装する

Handler.handleResponse() メソッドは、バックエンド コンポーネントによって処理された SOAP の応答メッセージをインターセプトするために呼び出されますが、この Web サービスを呼び出したクライアント アプリケーションに返される前に呼び出されます。そのシグネチャは次のとおりです。

  public boolean handleResponse(MessageContext mc) throws JAXRPCException  {}

このメソッドを実装すると、クライアント アプリケーションに返される前に SOAP メッセージに含まれているデータを暗号化したり、戻り値に処理を加えたりできます。

MessageContext オブジェクトは、SOAP メッセージ ハンドラによって処理されたメッセージのコンテキストを抽出します。MessageContext プロパティにより、ハンドラ チェーン内のハンドラは処理ステートを共有できます。

MessageContextSOAPMessageContext サブインタフェースを使用すると、SOAP の応答メッセージの内容を取得または更新することができます。SOAP の応答メッセージそのものは、javax.xml.soap.SOAPMessage オブジェクトに格納されます。「SAAJ を使用した SOAP リクエスト メッセージおよび応答メッセージの直接操作」を参照してください。

SOAPMessageContext クラスは、SOAP 応答を処理する次の 2 つのメソッドを定義します。

SOAP 応答のすべての処理をコーディングしたら、次のいずれかを実行します。

Handler.handleFault() メソッドを実装する

Handler.handleFault() メソッドは、SOAP メッセージ処理モデルに基づいて SOAP 障害を処理します。そのシグネチャは次のとおりです。

    public boolean handleFault(MessageContext mc) throws JAXRPCException  {}

このメソッドを実装すると、バックエンドコンポーネントによって生成された障害のほか、handleResponse() メソッドおよび handleRequest() メソッドによって生成されたあらゆる SOAP 障害の処理も扱うことができます。

MessageContext オブジェクトは、SOAP メッセージ ハンドラによって処理されたメッセージのコンテキストを抽出します。MessageContext プロパティにより、ハンドラ チェーン内のハンドラは処理ステートを共有できます。

MessageContextSOAPMessageContext サブインタフェースを使用すると、SOAP メッセージの内容を取得または更新することができます。SOAP メッセージそのものは、javax.xml.soap.SOAPMessage オブジェクトに格納されます。「SAAJ を使用した SOAP リクエスト メッセージおよび応答メッセージの直接操作」を参照してください。

SOAPMessageContext クラスは、SOAP メッセージを処理する次の 2 つのメソッドを定義します。

SOAP 障害のすべての処理をコーディングしたら、次のいずれかを実行します。

SAAJ を使用した SOAP リクエスト メッセージおよび応答メッセージの直接操作

javax.xml.soap.SOAPMessage 抽象クラスは、SOAP With Attachments API for Java 1.1 (SAAJ) 仕様の構成要素です。このクラスは、SOAP メッセージ ハンドラ作成時に SOAP のリクエスト メッセージおよび応答メッセージを操作するのに使用します。この節では、SOAPMessage オブジェクトの基本構造と SOAP メッセージの表示および更新に役立つメソッドのいくつかについて説明します。

SOAPMessage オブジェクトは、SOAPPart オブジェクト (SOAP XML ドキュメントそのものが入っている)、または同オブジェクトと添付ファイルで構成されています。

SOAPMessage クラスの詳細な説明については、SAAJ に関する Javadoc を参照してください。SAAJ の詳細については、「http://java.sun.com/xml/saaj/index.html」を参照してください。

SOAPPart オブジェクト

SOAPPart オブジェクトには、SOAPEnvelope オブジェクトに格納された XML SOAP ドキュメントが入っています。このオブジェクトは、実際の SOAP のヘッダと本文を取得するのに使用します。

次の Java コードのサンプルは、Handler クラスによって提供された MessageContext オブジェクトから SOAP メッセージを取り出して、その各部を参照する方法を示しています。

SOAPMessage soapMessage =  messageContext.getRequest();
SOAPPart soapPart = soapMessage.getSOAPPart();
SOAPEnvelope soapEnvelope = soapPart.getEnvelope();
SOAPBody soapBody = soapEnvelope.getBody();
SOAPHeader soapHeader = soapEnvelope.getHeader();

AttachmentPart オブジェクト

javax.xml.soap.AttachmentPart オブジェクトには、SOAP メッセージに対するオプションの添付ファイルが入っています。添付ファイルは、SOAP メッセージの残りの部分とは異なり、XML フォーマットの必須部分ではないので、その形式は、単純なテキストから画像ファイルまで、さまざまです。

警告 :SOAP メッセージ ハンドラから直接に添付ファイル java.awt.Image にアクセスする場合は、「SOAP メッセージ ハンドラでの画像添付ファイルの操作」で重要情報を参照してください。

添付ファイルを操作するには、SOAPMessage クラスの以下のメソッドを使用します。

次の例では、SAAJ API を使用して SOAP 添付ファイルにアクセスする SOAP メッセージ ハンドラの作成方法を示します。この例は、JAX-RPC ハンドラ API の WebLogic Server 拡張クラスである weblogic.webservice.GenericHandler 抽象クラスを使用しています。GenericHandler クラスの詳細については、「GenericHandler Abstract クラスの拡張」を参照してください。

import java.util.Iterator;
import javax.xml.rpc.handler.MessageContext;
import javax.xml.rpc.handler.soap.SOAPMessageContext;
import javax.xml.rpc.JAXRPCException;
import javax.xml.soap.AttachmentPart;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import weblogic.webservice.GenericHandler;
import weblogic.utils.Debug;
public final class ServerHandler
extends GenericHandler
{
public boolean handleRequest(MessageContext m) {
    SOAPMessageContext ctx = (SOAPMessageContext) m;
    SOAPMessage request = ctx.getMessage();
    if (request.countAttachments() == 0) {
throw new JAXRPCException("** Expected attachments");
}
    Iterator it = request.getAttachments();
    try {
while(it.hasNext()) {
AttachmentPart part = (AttachmentPart) it.next();
Debug.say("** Received attachment: "+
part.getContent());
}
} catch (SOAPException e) {
e.printStackTrace();
throw new JAXRPCException(e);
}
    return true;
  }
public boolean handleResponse(MessageContext m) {
    SOAPMessageContext ctx = (SOAPMessageContext) m;
    SOAPMessage response = ctx.getMessage();
    if (response.countAttachments() != 0) {
throw new JAXRPCException("** Expected no attachments");
}
    AttachmentPart part = response.createAttachmentPart();
    part.setContent("<weblogic>RESPONSE</weblogic>", "text/xml");
response.addAttachmentPart(part);
    return true;
}
}

SOAP メッセージ ハンドラでの画像添付ファイルの操作

この節では、添付ファイル java.awt.Image にアクセスする SOAP メッセージ ハンドラを作成すること、および clientgen Ant タスクによって生成されたクライアント JAX-RPC スタブを使用するクライアント アプリケーションから Image が送信されていることを前提としています。

clientgen Ant タスクによって生成されたクライアント コードでは、添付ファイル java.awt.Imageimage/gif ではなく text/xml の MIME タイプで、呼び出される WebLogic Web サービスに送信され、Image は画像を表す整数のストリームにシリアライズされます。特に、このクライアント コードは次のフォーマットで Image をシリアライズします。

つまり、受信した Image 添付ファイルを操作する SOAP メッセージ ハンドラでは、このデータ ストリームをデシリアライズして元の Image を作成し直す必要があるということです。

次の例は、SOAP メッセージの添付ファイルを反復処理し、各添付ファイルについて、入力ストリームを取得し、それを java.awt.Image にデシリアライズしてから、Java Swing のクラスを使用してフレームに表示する Handler インタフェースの handleRequest() メソッドの実装を示しています。ハンドラでは、すべての添付ファイルが Image であると想定しています。

// このハンドラでは、すべての添付ファイルが Image 添付ファイルであると想定している
  public boolean handleRequest(MessageContext mc)
{
try {
SOAPMessageContext messageContext = (SOAPMessageContext) mc;
       SOAPMessage soapmsg = messageContext.getMessage();
Iterator iter = soapmsg.getAttachments();
       // 添付ファイルを反復処理する
while ( iter.hasNext() ) {
AttachmentPart part = (AttachmentPart) iter.next();
         // 添付ファイルから入力ストリームを取得し、バイトを byte[] に読み込む
         DataHandler dh = part.getDataHandler();
InputStream is = dh.getInputStream();
int size = is.available();
byte[] bytes = new byte[size];
is.read( bytes, 0, size);
         // byte[] から文字列を作成する
String content = new String(bytes);
         // 文字列をデコードする
byte[] bin = weblogic.xml.schema.types.XSDBase64Binary.convertXml(content );
         // バイナリ オブジェクトの入力ストリームを取得する
ByteArrayInputStream in = new ByteArrayInputStream( bin );
ObjectInputStream oin = new ObjectInputStream( in );
         // ストリームをデシリアライズする
// 画像のフォーマットは次のとおり
// int width
// int height
// int[] pix -- ピクセルの配列
int width = oin.readInt();
int height = oin.readInt();
int[] pix = (int[])oin.readObject();
         // デシリアライズの結果から Image を作成する
java.awt.image.MemoryImageSource source =
new java.awt.image.MemoryImageSource(width, height, pix, 0, width);
         // フレームに画像を表示するサンプル コード
java.awt.Panel panel = new java.awt.Panel();
java.awt.Image image = panel.createImage( source );
        javax.swing.ImageIcon ii = new javax.swing.ImageIcon(image);
javax.swing.JLabel label = new javax.swing.JLabel(ii);
javax.swing.JFrame mainframe = new javax.swing.JFrame();
mainframe.getContentPane().add(label);
mainframe.pack();
mainframe.setVisible(true);
}
} catch (Exception ex) { ex.printStackTrace(); }
    return true;
}

 


GenericHandler Abstract クラスの拡張

WebLogic Server には、SOAP メッセージ ハンドラ クラスの Java コードの簡素化に役立つ、JAX-RPC ハンドラ API の拡張クラスが組み込まれています。この拡張クラスは、weblogic.webservices.GenericHandler という抽象クラスです。このクラスは、JAX-RPC javax.xml.rpc.handler.Handler インタフェースを実装します。

注意 :weblogic.webservices.GenericHandler 抽象クラスは元々は、JAX-RPC 仕様がまだ最終ではなくこの機能が含まれていないときに WebLogic Server 向けに開発されました。ただし現在は、JAX-RPC には WebLogic Server のクラスとほぼ同じそれ独自の GenericHandler クラスがあるので、WebLogic 固有のクラスではなく標準の JAX-RPC 抽象クラスを使用することを強くお勧めします。この節の説明は、互換性上の理由でのみ提供されています。JAX-RPC の javax.xml.rpc.handler.GenericHandler 抽象クラスの詳細については、「JAX-RPC の Javadoc」を参照してください。

GenericHandler は抽象クラスなので、実装する必要があるのは、実際のコードが格納されるメソッドのみです。特に機能を持たないものも含めた、Handler インタフェースのメソッドをすべて実装する必要はありません。たとえば、ハンドラが初期化パラメータを使用せず、追加のリソースを割り当てる必要がない場合、init() メソッドは実装する必要がありません。

クラスは次のように定義されます。

package weblogic.webservice;
import javax.xml.rpc.handler.Handler;
import javax.xml.rpc.handler.HandlerInfo;
import javax.xml.rpc.handler.MessageContext;
import javax.xml.namespace.QName;
/**
* @author Copyright (c) 2002 by BEA Systems. All Rights Reserved.
*/
public abstract class GenericHandler
implements Handler
{
  private HandlerInfo handlerInfo;
  public void init(HandlerInfo handlerInfo) {
this.handlerInfo = handlerInfo;
}
  protected HandlerInfo getHandlerInfo() { return handlerInfo; }
  public boolean handleRequest(MessageContext msg) {
return true;
}
  public boolean handleResponse(MessageContext msg) {
return true;
}
  public boolean handleFault(MessageContext msg) {}
  public void destroy() {}
public QName[] getHeaders() { return handlerInfo.getHeaders(); }
}

次のサンプルコードは examples.webservices.handler.nocomponent 製品サンプルからの抜粋ですが、GenericHandler 抽象クラスを使用して自分でハンドラを作成する方法を示しています。この例では、handleRequest() メソッドと handleResponse() メソッドのみを実装しています。init()destroy()getHeaders()、および handleFault() の各メソッドは実装していません (したがってコードには含まれていません)。

package examples.webservices.handler.nocomponent;
import java.util.Map;
import javax.xml.rpc.JAXRPCException;
import javax.xml.rpc.handler.MessageContext;
import javax.xml.rpc.handler.soap.SOAPMessageContext;
import javax.xml.soap.*;
import weblogic.webservice.GenericHandler;
import weblogic.utils.Debug;
/**
* @author Copyright (c) 2002 by BEA Systems. All Rights Reserved.
*/
public final class EchoStringHandler
extends GenericHandler
{
private int me = System.identityHashCode(this);
  public boolean handleRequest(MessageContext messageContext) {
System.err.println("** handleRequest called in: "+me);
return true;
}
  public boolean handleResponse(MessageContext messageContext) {
    try {
MessageFactory messageFactory = MessageFactory.newInstance();
      SOAPMessage m = messageFactory.createMessage();
      SOAPEnvelope env = m.getSOAPPart().getEnvelope();
      SOAPBody body = env.getBody();
      SOAPElement fResponse =
body.addBodyElement(env.createName("echoResponse"));
      fResponse.addAttribute(env.createName("encodingStyle"),
"http://schemas.xmlsoap.org/soap/encoding/");
      SOAPElement result =
fResponse.addChildElement(env.createName("result"));
      result.addTextNode("Hello World");
      ((SOAPMessageContext)messageContext).setMessage(m);
      return true;
    } catch (SOAPException e) {
e.printStackTrace();
throw new JAXRPCException(e);
}
}
}

 


SOAP メッセージ ハンドラ情報による web-services.xml ファイルの更新

web-services.xml デプロイメント記述子ファイルは、Web サービス用に定義されている SOAP メッセージ ハンドラおよびハンドラ チェーンを、実行順に記述します。

ハンドラ情報で web-services.xml ファイルを更新するには、次の手順に従います。

  1. この Web サービス用に定義されたすべてのハンドラ チェーンのリストが格納される <web-services> ルート要素の <handler-chains> 子要素を作成します。
  2. <handler-chains> 要素の <handler-chain> 子要素を作成します。この要素内に、そのハンドラ チェーンにあるすべてのハンドラがリストされます。各ハンドラに対して、class-name 属性を使用してそのハンドラを実装する Java クラスの完全修飾名を指定します。<init-params> 要素を使用して、ハンドラの任意の初期化パラメータを指定します。
  3. 次のサンプル コードからの抜粋は、3 つのハンドラ (最初のハンドラに初期化パラメータがある) の入った、myChain というハンドラ チェーンを示しています。

    <web-services>
    <handler-chains>
    <handler-chain name="myChain">
    <handler class-name="myHandlers.handlerOne" >
    <init-params>
    <init-param name="debug" value="on" />
    </init-params>
    </handler>
    <handler class-name="myHandlers.handlerTwo" />
    <handler class-name="myHandlers.handlerThree" />
    </handler-chain>
    </handler-chains>
    ...
    </web-services>
  4. <operations> 要素 (この要素自体も <web-service> 要素の子要素) の <operation> 子要素を使用して、このハンドラ チェーンが、この Web サービスのオペレーションとなるように指定します。次の 2 つのシナリオのいずれかに従います。

 


クライアント アプリケーションでの SOAP メッセージ ハンドラとハンドラ チェーンの使い方

この章では、WebLogic Server で動作する Web サービスの一環として実行されるハンドラ チェーンの SOAP メッセージ ハンドラを作成する方法について説明してきました。それ以外にも、クライアント アプリケーションで実行されるハンドラを作成することができます。クライアントサイド ハンドラの場合、ハンドラは次のようにクライアントが Web サービスを呼び出すときに 2 度実行されます。

クライアントサイド ハンドラは、サーバサイド ハンドラと同じ方法で作成できます。つまり、javax.rpc.xml.handler.Handler インタフェースを実装する Java クラスを記述します。多くの場合、WebLogic Server で実行される Web サービスとその Web サービスを呼び出すクライアント アプリケーションで同じハンドラ クラスを使用できます。たとえば、サーバおよびクライアント用として、送信および受信したすべての SOAP メッセージをログに記録する汎用ロギング ハンドラを記述できます。 ハンドラ Java クラスの記述の詳細については、「ハンドラ インタフェースの実装」を参照してください。

クライアントサイド ハンドラ クラスを記述したら、クライアント アプリケーションでそのハンドラを登録します。このプロセスはサーバの場合と異なります。クライアント アプリケーションにはデプロイメント記述子が存在しないので、javax.xml.rpc.handler.HandlerInfo および javax.xml.rpc.handler.HandlerRegistry クラスを使用して、ハンドラをプログラムによって登録する必要があります。次のクライアント アプリケーション例に、そのための方法を示します。太字の部分については、この例の後に説明します。

import java.util.ArrayList;
import java.io.IOException;
import javax.xml.namespace.QName;
import javax.xml.rpc.ServiceException;
import javax.xml.rpc.handler.HandlerInfo;
import javax.xml.rpc.handler.HandlerRegistry;
public class Main{
  public static void main( String[] args ){
    if( args.length == 1 ){
new Main( args[0] );
}else{
throw new IllegalArgumentException( "URL of the service not specified" );
}
}
  public Main( String wsdlUrl ){
try{
      HelloWorldService service = new HelloWorldService_Impl( wsdlUrl );
HelloWorldServicePort port = service.getHelloWorldServicePort();
      QName portName = new QName( "http://tutorial/sample4/", 
"HelloWorldServicePort");
      HandlerRegistry registry = service.getHandlerRegistry();
      List handlerList = new ArrayList();
handlerList.add( new HandlerInfo( ClientHandler.class, null, null ) );
      registry.setHandlerChain( portName, handlerList );
      System.out.println( port.helloWorld() );
}catch( IOException e ){
System.out.println( "Failed to create web service client:" + e );
}catch( ServiceException e ){
System.out.println( "Failed to create web service client:" + e );
}
}
}

上記の例で注目すべき主な点は以下のとおりです。

 


バックエンド コンポーネントからハンドラの MessageContext へのアクセス

Handler インタフェースを実装してハンドラを作成する場合、MessageContext.setProperty() メソッドを使用して、ハンドラ メソッド (handleRequest() など) に MessageContext オブジェクトのプロパティを設定できます。ハンドラ チェーンの後に呼び出されるバックエンド コンポーネントからこれらのプロパティにアクセスするには、weblogic.webservice.context.WebServiceContext API を使用して MessageContext を取得する必要があります。

たとえば、次のコードの抜粋では、ユーザ定義のプロパティ TransIDMessageContext オブジェクトに設定する Handler.handleRequest() メソッドの実装を示します。

import javax.xml.rpc.handler.MessageContext;
 ...
 public boolean handleRequest(MessageContext mc) {
try {
mc.setProperty("TransId", "AX123");
}
catch (Exception ex) {
System.out.println("exception from Handler: " + ex.getLocalizedMessage());
}
   return true;
}

バックエンド コンポーネントを実装する Java クラスの次のサンプル コードでは、weblogic.webservice.context.WebServiceContext API を使用して TransID プロパティにアクセスする方法を示します。

import javax.xml.rpc.handler.soap.SOAPMessageContext;
import javax.xml.rpc.handler.MessageContext;
import weblogic.webservice.context.WebServiceContext;
 ...
  public String someMethod(String s) {
try {
SOAPMessageContext soapMessageContext =
WebServiceContext.currentContext().getLastMessageContext();
String somePropery = (String)soapMessageContext.getProperty("TransId");
System.out.println("TransId =" + someProperty);
   }
catch(Exception ex) {
System.out.println("exception from service: " + ex.getLocalizedMessage());
}
   return s;
}

 

フッタのナビゲーションのスキップ  ページの先頭 前 次