WebLogic Web サービス プログラマーズ ガイド
![]() |
![]() |
![]() |
![]() |
この章では、WebLogic Web サービスの開発中に、SOAP メッセージ ハンドラを使用して SOAP のリクエスト メッセージおよび応答メッセージをインターセプトする方法について説明します。
SOAP メッセージ ハンドラは、Web サービスのリクエストと応答の両方で SOAP メッセージをインターセプトします。ハンドラは、Web サービスそのものと Web サービスを呼び出すクライアント アプリケーションの両方で作成することができます。ハンドラをどのような場合に使用するかについては、「SOAP メッセージをインターセプトする SOAP メッセージ ハンドラの使用」を参照してください。
次の表は、javax.xml.rpc.handler
API の主なクラスおよびインタフェースの説明です。それらを使用してハンドラを作成する方法については、この章で後述します。
次の手順は、servicegen
Ant タスクを使用して WebLogic Web サービスをすでに実装およびアセンブルしていて、かつハンドラおよびハンドラ チェーンを追加して Web サービスを更新することを前提としています。
javax.xml.rpc.handler.Handler
インタフェースを実装する Java クラスを作成します。「ハンドラ インタフェースの実装」を参照してください。WebLogic Server には、ハンドラ クラスのコーディングの簡素化に役立つ、JAX-RPC ハンドラ API の拡張クラスが組み込まれています。weblogic.webservice.GenericHandler
という抽象クラスです。「GenericHandler Abstract クラスの拡張」を参照してください。
<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 ファイルの更新」を参照してください。
クライアントサイド SOAP メッセージ ハンドラおよびハンドラ チェーンの詳細については、「クライアント アプリケーションでの SOAP メッセージ ハンドラとハンドラ チェーンの使い方」を参照してください。
SOAP メッセージ ハンドラを設計するときには、以下の事項を決める必要があります。
ハンドラ チェーン内の各ハンドラには、SOAP のリクエスト メッセージを処理するメソッドと SOAP の応答メッセージを処理するメソッドが 1 つずつあります。これらのハンドラは、web-services.xml
デプロイメント記述子ファイルで指定します。順序付けされたハンドラのグループが、ハンドラ チェーンです。
Web サービスを呼び出すときに、WebLogic Server は次のようにハンドラを実行します。
handleRequest()
メソッドはすべて、web-services.xml
ファイルで指定されている順序で実行されます。これらの handleRequest()
メソッドのいずれもが、SOAP のリクエスト メッセージを変更できます。handleRequest()
メソッドが実行されると、WebLogic Server は、Web サービスを実装するバックエンド コンポーネントを呼び出し、最終的な SOAP のリクエスト メッセージを渡します。 注意 :この操作は、この Web サービスに対してバックエンド コンポーネントが実際に定義されている場合にのみ発生します。ハンドラ チェーンのみで構成される Web サービスを開発することもできます。
たとえば、次の例のように、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()
メソッドが実行される順序を示しています。
通常、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 インタフェースには実装する必要のある以下のメソッドが含まれています。
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) 仕様の構成要素です。詳細については、「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
オブジェクトのインスタンスを作成し、そのインスタンスが自動的に初期化されるようにするために呼び出されます。そのシグネチャは次のとおりです。
public void init(HandlerInfo config) throws JAXRPCException {}
HandlerInfo
オブジェクトには、web-services.xml
ファイルで指定されている初期化パラメータをはじめとする、SOAP メッセージ ハンドラについての情報が格納されています。HandlerInfo.getHandlerConfig()
メソッドを使用してパラメータを取得すると、このメソッドは、名前と値の組み合わせの入った Map
オブジェクトを返します。
初期化パラメータを処理する必要がある場合、または、他の初期化タスクを実行する必要がある場合は、init()
メソッドを実装します。
初期化パラメータの使用例としては、デバッグのオン、オフ、メッセージやエラーを書き込むためのログ ファイルの名前の指定などがあります。
Handler.destroy()
メソッドは、Handler
オブジェクトのインスタンスを破棄するために呼び出されます。そのシグネチャは次のとおりです。
public void destroy() throws JAXRPCException {}
destroy()
メソッドを実装すると、ハンドラのライフサイクルを通じて取得されたあらゆるリソースを解放できます。
Handler.getHeaders()
メソッドは、このハンドラ インスタンスで処理されたヘッダ ブロックを取得します。そのシグネチャは次のとおりです。
public QName[] getHeaders() {}
Handler.handleRequest()
メソッドは、バックエンド コンポーネントによって処理される前に SOAP のリクエスト メッセージをインターセプトするために呼び出されます。そのシグネチャは次のとおりです。
public boolean handleRequest(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
を返すことにより、ハンドラ リクエスト チェーン内の次のハンドラを呼び出す。 リクエスト チェーンの次のハンドラは、web-services.xml
デプロイメント記述子にある <handler-chain>
要素の次の <handler>
下位要素として指定されています。チェーン内のすべてのハンドラが実行されたら、Web サービスのコンフィグレーションによって、メソッドは、バックエンド コンポーネントの呼び出し、最終的な SOAP のリクエスト メッセージの送信、または最後のハンドラの handleResponse()
メソッドの呼び出しを行います。
false
を返すことにより、ハンドラ リクエスト チェーンの処理をブロックする。 ハンドラ リクエスト チェーンの処理をブロックすると、Web サービスのこの呼び出しについては、バックエンド コンポーネントは実行されなくなります。Web サービスの一部の呼び出しの結果をキャッシュしてあり、そのリストに現在の呼び出しも含まれている場合は、この操作が便利な場合があります。
ハンドラ リクエスト チェーンの処理を中断されますが、WebLogic Server が、現在のハンドラから順に、response チェーンを呼び出します。たとえば、ハンドラ チェーンに、handlerA と handlerB という 2 つのハンドラがあると想定します。ここで、handlerA の handleRequest()
メソッドは、handlerB の対応するメソッドの前に呼び出されるものとします。handlerA で処理がブロックされると (したがって handlerB の handleRequest()
メソッドは呼び出されない)、ハンドラ応答チェーンは handlerA で開始され、handlerB の handleRequest()
メソッドも呼び出されません。
javax.xml.rpc.soap.SOAPFaultException
を送出して、SOAP 障害を示す。handleRequest()
メソッドが SOAPFaultException
を送出すると、WebLogic Server は、この例外を検出して、ハンドラ リクエスト チェーンの後続の処理を終了し、このハンドラの handleFault()
メソッドを呼び出します。
JAXRPCException
を送出する。 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
を返すことにより、ハンドラ応答チェーン内の次のハンドラを呼び出す。 ハンドラ チェーンの次の応答は、web-services.xml
デプロイメント記述子にある <handler-chain>
要素の先行する <handler>
下位要素として指定されています (ハンドラ チェーン上の応答は、web-services.xml
ファイルで指定されたのと逆の順序で実行されることに留意してください。詳細については、「SOAP メッセージ ハンドラおよびハンドラ チェーンの設計」を参照してください)。
ハンドラ チェーン内のすべてのハンドラが実行されたら、メソッドは、この Web サービスを呼び出したクライアント アプリケーションに最終的な SOAP の応答メッセージを返します。
false
を返すことにより、ハンドラ応答チェーンの処理をブロックする。 ハンドラ応答チェーンの処理をブロックすると、応答チェーンにある残りのハンドラが、Web サービスのこの呼び出しについては実行されなくなり、現在の SOAP メッセージがクライアント アプリケーションに返されます。
JAXRPCException
を送出する。 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 障害のすべての処理をコーディングしたら、次のいずれかを実行します。
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
オブジェクトには、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();
javax.xml.soap.AttachmentPart
オブジェクトには、SOAP メッセージに対するオプションの添付ファイルが入っています。添付ファイルは、SOAP メッセージの残りの部分とは異なり、XML フォーマットの必須部分ではないので、その形式は、単純なテキストから画像ファイルまで、さまざまです。
警告 :SOAP メッセージ ハンドラから直接に添付ファイル java.awt.Image
にアクセスする場合は、「SOAP メッセージ ハンドラでの画像添付ファイルの操作」で重要情報を参照してください。
添付ファイルを操作するには、SOAPMessage
クラスの以下のメソッドを使用します。
countAttachments()
: この SOAP メッセージに含まれている添付ファイルの数を返します。getAttachments()
: すべての添付ファイルを取り出し、(AttachmentPart
オブジェクトとして) Iterator
オブジェクトに格納します。createAttachmentPart()
: 他のタイプの Object
から AttachmentPart
オブジェクトを作成します。addAttachmentPart()
: 作成された AttachmentPart
オブジェクトを 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;
}
}
この節では、添付ファイル java.awt.Image
にアクセスする SOAP メッセージ ハンドラを作成すること、および clientgen
Ant タスクによって生成されたクライアント JAX-RPC スタブを使用するクライアント アプリケーションから Image
が送信されていることを前提としています。
clientgen
Ant タスクによって生成されたクライアント コードでは、添付ファイル java.awt.Image
は image/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;
}
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);
}
}
}
web-services.xml
デプロイメント記述子ファイルは、Web サービス用に定義されている SOAP メッセージ ハンドラおよびハンドラ チェーンを、実行順に記述します。
ハンドラ情報で web-services.xml
ファイルを更新するには、次の手順に従います。
<handler-chains>
要素の <handler-chain>
子要素を作成します。この要素内に、そのハンドラ チェーンにあるすべてのハンドラがリストされます。各ハンドラに対して、class-name
属性を使用してそのハンドラを実装する Java クラスの完全修飾名を指定します。<init-params>
要素を使用して、ハンドラの任意の初期化パラメータを指定します。次のサンプル コードからの抜粋は、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>
<operations>
要素 (この要素自体も <web-service>
要素の子要素) の <operation>
子要素を使用して、このハンドラ チェーンが、この Web サービスのオペレーションとなるように指定します。次の 2 つのシナリオのいずれかに従います。この場合は、次の web-services.xml
ファイルからの抜粋のように、<operation>
要素の component
、method
、handler-chain
の各属性を使用します。
<web-service>
<components>
<stateless-ejb name="myEJB">
...
</stateless-ejb>
</components>
<operations>
<operation name="getQuote"
method="getQuote"
component="myEJB"
handler-chain="myChain" />
</operations>
</web-service>
この例では、myChain
ハンドラ チェーンのリクエスト チェーンが最初に実行され、次に、myEJB
ステートレス セッション EJB の getQuote()
メソッドが実行され、最後に myChain
の応答チェーンが実行されます。
この章では、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 );
}
}
}
HandlerInfo
および HandlerRegistry
クラスをインポートする。これらのクラスは、クライアントサイド ハンドラ クラスを登録するために使用されます。
import javax.xml.rpc.handler.HandlerInfo;
import javax.xml.rpc.handler.HandlerRegistry;
QName
オブジェクトを作成する。
QName portName = new QName( "http://tutorial/sample4/",
"HelloWorldServicePort");
HandlerRegistry
オブジェクトを作成する。
HandlerRegistry registry = service.getHandlerRegistry();
List
オブジェクトを作成する。このリストは、クライアントサイド ハンドラ チェーンになります。HandlerInfo
クラスを使用して、Java ハンドラ クラスの名前を指定します。
List handlerList = new ArrayList();
handlerList.add( new HandlerInfo( ClientHandler.class, null, null ) );
警告 :List
オブジェクトにハンドラを追加する順序によって、クライアント アプリケーションでハンドラが実行される順序が指定されます。たとえば、HandlerA.class
を最初に実行し、次に HandlerB.class
を実行する場合、HandlerA.class
を HandlerB.class
の前に追加する必要があります。
HandlerRegistry.setHandlerChain()
メソッドを使用して、ハンドラ チェーンをクライアント アプリケーションに登録する。
registry.setHandlerChain( portName, handlerList );
Handler
インタフェースを実装してハンドラを作成する場合、MessageContext.setProperty()
メソッドを使用して、ハンドラ メソッド (handleRequest()
など) に MessageContext
オブジェクトのプロパティを設定できます。ハンドラ チェーンの後に呼び出されるバックエンド コンポーネントからこれらのプロパティにアクセスするには、weblogic.webservice.context.WebServiceContext
API を使用して MessageContext
を取得する必要があります。
たとえば、次のコードの抜粋では、ユーザ定義のプロパティ TransID
を MessageContext
オブジェクトに設定する 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;
}
![]() ![]() |
![]() |
![]() |