プライマリ・コンテンツに移動
Oracle® Fusion Middleware Oracle WebLogic Server JAX-WS Webサービスの開発
12c (12.2.1)
E69970-01
  目次へ移動
目次

前
 
次
 

18 SOAPメッセージ・ハンドラの作成と使用

この章では、Java API for XML Web Services (JAX-WS)を使用したWebLogic WebサービスでSOAPメッセージ・ハンドラを作成および使用する方法について説明します。

この章の内容は次のとおりです:

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など)ポリシーと一緒に使用した場合、ユーザー定義のメッセージ・ハンドラの実行前に、ポリシーのインターセプタが実行されます。アウトバウンド・メッセージの場合、この順序は逆になります。

サーバー側SOAPメッセージ・ハンドラの追加:主な手順

次の手順では、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メッセージ・ハンドラの追加:主な手順

クライアント側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メッセージを処理する別個のメソッドを定義します。一方、SOAPリクエストのみを処理し、それと同等のレスポンス処理は行わないハンドラを設計することもできます。また、ハンドラ・チェーン内の次のハンドラを呼び出さず、そのまま、任意の時点でクライアント・アプリケーションにレスポンスを送信することも可能です。

サーバー側ハンドラの実行

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

  1. ハンドラ・チェーン内のハンドラのinboundメソッドはすべて、JWSアノテーションで指定されている順序で実行されます。これらのinboundメソッドのいずれもが、SOAPのリクエスト・メッセージを変更できます。

  2. ハンドラ・チェーン内の最後のハンドラが実行されると、WebLogic Serverは、Webサービスを実装するバックエンド・コンポーネントを呼び出し、最終的なSOAPのリクエスト・メッセージを渡します。

  3. バックエンド・コンポーネントの実行が終了したら、ハンドラ・チェーン内のハンドラのoutboundメソッドが、JWSアノテーションで指定されているのとはの順序で実行されます。これらのoutboundメソッドのいずれもが、SOAPのレスポンス・メッセージを変更できます。

  4. ハンドラ・チェーン内の最初のハンドラが実行されると、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メソッドが実行される順序を示しています。

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

図18-1の説明が続きます
「図18-1 ハンドラ・メソッドの実行順序」の説明

クライアント側ハンドラの実行

クライアント側ハンドラの場合は、以下のタイミングで二度実行されます。

  • クライアント・アプリケーションがWebサービスにSOAPリクエストを送信する直前

  • クライアント・アプリケーションがWebサービスからSOAPレスポンスを受信した直後

SOAPメッセージ・ハンドラの作成

SOAPメッセージ・ハンドラには2つのタイプがあります。次の表にそれぞれの定義を示します。

表18-3 SOAPメッセージ・ハンドラのタイプ

ハンドラ・タイプ 説明

SOAPハンドラ

ヘッダーを含めたSOAPメッセージ全体へのアクセスを可能にします。SOAPハンドラは、javax.xml.ws.handler.soap.SOAPHandlerインタフェースを使用して定義します。呼出しには、javax.xml.ws.handler.MessageContextを拡張したjavax.xml.ws.handler.soap.SOAPMessageContextのインポートを使用します。SOAPMessageContext.getMessage()メソッドは、javax.xml.soap.SOAPMessageを返します。

論理ハンドラ

メッセージのペイロードへのアクセスを提供します。メッセージ内のプロトコル固有の情報(たとえばヘッダー)を変更することはできません。論理ハンドラは、javax.xml.ws.handler.LogicalHandlerインタフェースを使用して定義します。(http://docs.oracle.com/javaee/7/api/javax/xml/ws/handler/LogicalHandler.htmlを参照)。呼出しには、javax.xml.ws.handler.MessageContextを拡張したjavax.xml.ws.handler.LogicalMessageContextを使用します。LogicalMessageContext.getMessage()メソッドは、javax.xml.ws.LogicalMessageを返します。

ペイロードには、JAXBオブジェクトまたはjavax.xml.transform.Sourceオブジェクトとしてアクセスできます。(http://docs.oracle.com/javaee/7/api/javax/xml/ws/LogicalMessage.htmlを参照)。


両方のタイプのメッセージ・ハンドラが拡張するjavax.xml.ws.Handlerインタフェースは、次の表に示すメソッドを定義します。(http://docs.oracle.com/javaee/7/api/javax/xml/ws/handler/Handler.htmlを参照)。

表18-4 ハンドラ・インタフェース・メソッド

メソッド 説明
handleMessage()

インバウンドおよびアウトバウンド・メッセージの通常処理を管理します。MessageContextオブジェクトのプロパティは、メッセージがインバウンドか発信かを識別するために使用します。「Handler.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ハンドラのサンプル

次に、単純な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()メソッドの実装

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/7/api/javax/xml/ws/handler/MessageContext.htmlを参照)。ハンドラ・チェーン内のハンドラは、MessageContextプロパティを使用して、メッセージがインバウンドかアウトバウンドかを識別し、処理状態を共有します。MessageContextSOAPMessageContextまたは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()メソッドの実装

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/7/api/javax/xml/ws/handler/MessageContext.htmlを参照)。ハンドラ・チェーン内のハンドラは、MessageContextプロパティを使用して、メッセージがインバウンドかアウトバウンドかを識別し、処理状態を共有します。MessageContextLogicalMessageContextまたはSOAPMessageContextサブインタフェースを使用すると、SOAPメッセージまたは論理メッセージの内容を取得したり設定したりできます。詳細については、「メッセージ・コンテキスト・プロパティの値とメソッドの使用」を参照してください。

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

  • trueを返すことにより、ハンドラ・チェーン内の次のハンドラのhandleFault()メソッドを呼び出します。

  • falseを返すことにより、ハンドラ・フォルト・チェーンの処理をブロックします。

Handler.close()メソッドの実装

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/7/api/javax/xml/ws/handler/LogicalMessageContext.html)を参照してください。

表18-6 LogicalMessageContextクラスのメソッド

メソッド 説明
getMessage()

SOAPメッセージを含むjavax.xml.ws.LogicalMessageオブジェクトを取得します。


SOAPMessageContextクラスは、SOAPメッセージを処理する次のメソッドを定義します。詳細は、Javadocの「java.xml.ws.handler.soap.SOAPMessageContext」(http://docs.oracle.com/javaee/7/api/javax/xml/ws/handler/soap/SOAPMessageContext.html)を参照してください。


注意:

SOAPメッセージ自体は、(http://docs.oracle.com/javaee/7/api/javax/xml/soap/SOAPMessage.html)のjavax.xml.soap.SOAPMessageオブジェクトに格納されています。このオブジェクトの詳細は、「SAAJを使用したSOAPリクエスト・メッセージおよびレスポンス・メッセージの直接操作」を参照してください。

表18-7 SOAPMessageContextクラスのメソッド

メソッド 説明
getHeaders()

メッセージ・コンテキスト内のメッセージから、特定の修飾名のヘッダーを取得します。

getMessage()

SOAPメッセージを含むjavax.xml.soap.SOAPMessageオブジェクトを取得します。

getRoles()

ハンドラ・チェーンの実行に関連付けられているSOAPアクター・ロールを取得します。

setMessage()

SOAPメッセージを設定します。


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オブジェクト


注意:

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(); 

AttachmentPartオブジェクト

javax.xml.soap.AttachmentPartオブジェクト(http://docs.oracle.com/javaee/7/api/javax/xml/soap/AttachmentPart.htmlを参照)には、SOAPメッセージに対するオプションの添付ファイルが入っています。添付ファイルは、SOAPメッセージの残りの部分とは異なり、XMLフォーマットの必須部分ではないので、その形式は、単純なテキストからイメージ・ファイルまで、様々です。


注意:

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

添付ファイルを操作するには、SOAPMessageクラスの次のメソッドを使用します。詳細は、Javadocの「javax.xml.soap.SOAPMessage」(http://docs.oracle.com/javaee/7/api/javax/xml/soap/SOAPMessage.html)を参照してください。

表18-8 添付ファイルの操作に使用するSOAPMessageクラスのメソッド

メソッド 説明
addAttachmentPart()

作成されたAttachmentPartオブジェクトをSOAPMessageに追加します。

countAttachments()

このSOAPメッセージに含まれている添付ファイルの数を返します。

createAttachmentPart()

他のタイプのObjectからAttachmentPartオブジェクトを作成します。

getAttachments()

すべての添付ファイルをAttachmentPartオブジェクトとして取得し、Iteratorオブジェクトに格納します。


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

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

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

  • int width

  • int height

  • int[] pixels

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

JWSファイルでのハンドラ・チェーンの構成

@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サービスのコンパイルと再ビルド

この項では、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メッセージ・ハンドラの構成

クライアント側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>子要素を使用してカスタマイズ・ファイルに渡します。