Sun ONE ロゴ      前へ      目次      索引      次へ     
Sun ONE Message Queue 開発者ガイド



第 5 章   SOAP メッセージの操作


Sun ONE MQ では、SOAP ペイロードを含む JMS メッセージを送信できます。このため、高い信頼性で SOAP メッセージを転送できます。また、SOAP メッセージを JMS サブスクライバにパブリッシュすることもできます。この章では、次の手順を説明します。

  • MQ を使用しない SOAP メッセージの送受信

  • SOAP ペイロードを含む JMS メッセージの送受信

この章では、最初に SOAP 処理の概要を紹介し、添付ファイル付き SOAP メッセージ用の Java API (JAXM) について説明します。SOAP メッセージ処理を行うには、これらに関する知識が必要です。この章の最後の部分では、SOAP メッセージペイロードを含む JMS メッセージの作成方法について説明します。

SOAP 仕様について十分に理解している場合は、導入部分をとばして「Java での SOAP メッセージング」から読み始めてもかまいません。



SOAP とは



SOAP (Simple Object Access Protocol) は、分散環境内の複数のピア間で構造化データを交換するためのプロトコルです。交換されるデータの構造は、XML スキーマによって指定されます。

SOAP メッセージは、データをシステムに依存しない移植可能な方法で表現できる XML 形式でコード化されているため、移植可能です。XML でコード化されたデータには、レガシーシステムからアクセスできます。また、複数の企業間で同じデータを共有することもできます。SOAP テクノロジは、XML によるデータの統合という特徴を活かして、Web サービスなどの Web ベースのコンピューティングでも一般的に使用されます。ファイアウォールは、SOAP パケットをそのコンテンツタイプ (text/xml-SOAP) に基づいて認識します。また、SOAP メッセージヘッダーに含まれる情報に基づいてメッセージをフィルタリングします。

SOAP 仕様には、XML メッセージ交換のための規則が記載されています。SOAP 仕様は、XML でコード化された情報を交換する必要がある Web サービスの基盤を形成します。通信を行う双方が、コード化された情報の交換に使用する固有のプロトコルを定義してもかまいません。しかし、SOAP のような標準を採用すれば、開発者は情報交換をサポートする汎用の部品を構築できます。こうした部品は、基本的な SOAP 交換に新たな機能を追加するソフトウェアであったり、SOAP メッセージングを管理するツールであったり、SOAP 処理をサポートするオペレーティングシステムの一部分であったりします。このサポートが得られれば、その他の開発者は Web サービスの作成作業に集中できます。

SOAP プロトコルについては、Web サイト http://www.w3.org/TR/SOAP にすべて説明されています。この節では、SOAP を使用する理由と JAXM API の操作をより簡単にする基本的概念の一部の説明だけを行います。


SOAP と Java for XML Messaging API

Java API for XML Messaging (JAXM) は、SOAP 標準に準拠させるための Java ベースの API です。この API で SOAP メッセージをアセンブルまたは逆アセンブルすると、構文的に正しい SOAP メッセージが構築されます。また、メッセージを次の送り先に転送する前にその部分部分を複数のアプリケーションで処理する必要がある場合、JAXM を使用することによってメッセージ処理を自動化できます。

図 5-1 に、SOAP メッセージングの実装に使用される層を示します。この章では、SOAP と言語実装層に注目します。

図 5-1    SOAP メッセージング層
図は、SOAP メッセージングに必要な機能別層を示す。 図は文字で説明される

次の節では、先ほどの図に示した各層について詳しく説明します。この章の以降の部分では、SOAP と言語実装層に注目します。


トランスポート層

基礎となるメッセージングシステムは、回線上に送信されるメッセージの直列化と、送信先に着信したメッセージビットを解釈するトランスポートプロトコルまたはワイヤプロトコルです。SOAP メッセージの送信には、プロトコルをいくつ使ってもかまいません。しかし、SOAP 仕様に定義されているのは、HTTP とのバインディングだけです。SOAP は HTTP 要求/応答メッセージモデルを使用します。これにより、HTTP 要求内には SOAP 要求パラメータ、HTTP 応答内には SOAP 応答パラメータが設定されます。HTTP バインディングには、SOAP メッセージがファイアウォールを通過できるようにするという利点があります。


SOAP 層

トランスポート層の上には SOAP 層があります。この層は、SOAP 仕様書に定義されているとおり、メッセージの構成部分 (エンベロープ、ヘッダー、本体、添付ファイル) の識別に使用する XML スキームを指定します。添付ファイルを除く SOAP メッセージの部分とコンテンツは、すべて XML で書かれています。XML タグを使って SOAP タグを定義する方法については、次のサンプル SOAP メッセージを参照してください。


<SOAP-ENV: Envelope
   xmlns: SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
   SOAP-ENV: encodingStyle=
           "http://schemas.xmlsoap.org/soap/encoding/">

      <SOAP-ENV: Body>
          <m: GetLastTradePrice xmlns:m="Some-URI">
              <symbol>DIS</symbol>
          </m: GetLastTradePrice>
      </SOAP-ENV: Body>
</SOAP-ENV: Envelope>

SOAP メッセージングを行うために実際に必要なのは、ワイヤトランスポート層と SOAP 層です。送信するメッセージを定義する XML ドキュメントの作成や、メッセージを一方から送信し、もう一方で受信するための HTTP コマンドの作成も可能です。この場合、クライアントは、指定された URL へ同期方式でメッセージを送信することしかできません。残念ながら、このようなメッセージングの有効範囲と信頼性はかなり制限されています。このような制限を克服するため、SOAP メッセージングには、プロバイダ層とプロファイル層が追加されています。


プロバイダ層

図 5-1 では、プロバイダ層を言語実装と配信セマンティクスの 2 つの機能部分として示しています。

プロバイダ言語実装では、API 呼び出しを使って、SOAP に準拠した XML メッセージを作成できます。任意の JAXM が実装されていれば、Java クライアントは、SOAP メッセージとそのすべての部分を Java オブジェクトとして定義できます。クライアントは、JAXM を使ってコネクションを作成し、これを使ってメッセージを送信することもできます。同様に、Java で書かれた Web サービスも同じ (または別の) JAXM API 実装を使って、メッセージの受信、逆アセンブル、メッセージの受信の通知を行うことができます。


メッセージングのセマンティクス
SOAP プロバイダは、言語実装のほかに、メッセージ配信に関連するサービスを提供できます。たとえば、信頼性、持続性、セキュリティ、管理制御などのサービスがあります。MQ の将来のリリースでは、これらのサービスが SOAP メッセージング用として提供されます。


相互運用性
SOAP プロバイダは、SOAP 仕様に定義されているようにすべてのメッセージを構築または解体する必要があるため、SOAP を使用するクライアントとサービスには相互運用性があります。図 5-2 のように、SOAP メッセージングを行うクライアントとサービスは、同じ言語で書かれていなくてもかまいません。また、同じ SOAP プロバイダを使用していなくてもかまいません。標準化の必要があるのは、メッセージのパッケージのみです。

図 5-2    SOAP の相互運用性
図は、ある SOAP プロバイダを使用するクライアントが、別の SOAP プロバイダを使用するクライアントにメッセージを送信できることを示す。 図は文字で説明される

JAXM クライアントまたはサービスを、異なるプロバイダを使用するサービスまたはクライアントと相互運用するには、双方が次の 2 点について合意する必要があります。

  • 同じトランスポートバインディング (同じワイヤプロトコル) を使用する

  • 送信される SOAP メッセージの構築には同じプロファイルを使用する

次の節で説明するように、プロファイルには追加の処理情報が含まれています。


プロファイル層

SOAP メッセージングの最後の層、プロファイル層は、SOAP プロバイダ で SOAP メッセージングを使用するビジネスパートナー間のメッセージングセマンティクスを管理します。プロファイルは「ebxml」のような業界標準であり、メッセージ処理の追加の規則を定義します。プロバイダは、メッセージファクトリがメッセージを作成するとき、メッセージのヘッダーにプロファイル情報を追加できます。SOAP メッセージヘッダーは SOAP メッセージングの主要な拡張手段です。ebxml プロファイルのサポートは、MQ の将来のリリースで追加される予定です。


SOAP メッセージ

SOAP メッセージング層の概略を把握したところで、今度は SOAP メッセージ自体に注目します。XML で記述された SOAP メッセージの描画は JAXM ライブラリによって行われます。しかし、正しい順序で JAXM 呼び出しを行うには、その構造を把握しておく必要があります。

SOAP メッセージは、SOAP エンベロープ、オプションの SOAP ヘッダー、SOAP 本体からなる XML ドキュメントです。SOAP メッセージヘッダーには、1 つまたは複数の中間ノードを経て最終的な送信先までメッセージを配信するための情報が含まれています。

  • エンベロープは、メッセージを表す XML ドキュメントのルート要素です。これにより、メッセージが誰によってどのように処理されるかというフレームワークが定義されます。SOAP プロセッサは、エンベロープ要素を検出した時点で、その XML が SOAP メッセージであることを認識し、メッセージの各部分を検索できるようになります。

  • ヘッダーは、SOAP メッセージに機能を追加するための汎用メカニズムです。ヘッダーには、基本プロトコルの拡張機能を定義する子要素を含めることができます。子要素の数に制限はありません。たとえば、ヘッダーの子要素によって定義されるものとして、認証情報、トランザクション情報、ロケール情報などがあります。メッセージを処理するソフトウェアをアクターと呼びます。アクターは、ヘッダーのメカニズムを使って、ある機能が必須機能であるのかオプション機能であるのか、また誰によって使用されるのかを事前の合意なしで定義します。

  • 本体は、メッセージの最終的な受信者向けの必須情報を格納するコンテナです。

SOAP メッセージには添付ファイルが付属している場合もあります。添付ファイルは XML で記述されていなくてもかまいません。詳細は、次の「SOAP パッケージ化モデル」を参照してください。

SOAP メッセージは入れ子構造になっています。JAXM を使ってメッセージのアセンブルまたは逆アセンブルを行うとき、必要なメッセージ部分を取得するには、適切な順序で API 呼び出しを行う必要があります。たとえば、メッセージに新しいコンテンツを追加する場合、メッセージの本体部分を取得する必要があります。このためには、入れ子になった SOAP 部分、SOAP エンベロープ、SOAP 本体を使って、データの指定に使用する SOAP 本体要素を取得する必要があります。詳細は、「SOAP メッセージオブジェクト」を参照してください。


SOAP パッケージ化モデル

SOAP 仕様には、SOAP メッセージの 2 つのモデルが記述されています。1 つは完全に XML でエンコードされたモデルであり、1 つは XML 以外のデータの含む添付ファイルを送信元が追加できるようにするモデルです。次の 2 つの図を参照して、各モデルの SOAP メッセージの部分を確認してください。JAXM を使って SOAP メッセージとその部分を定義すると、この情報を理解しやすくなります。

図 5-3 は、添付ファイルのない SOAP モデルを示します。このパッケージには、SOAP エンベロープ、ヘッダー、本体が含まれています。ヘッダーはオプションです。

図 5-3    添付ファイルのない SOAP メッセージ
図は、エンベロープに同封されたメッセージ本体とヘッダーを示す。さらに、エンベロープはメッセージパッケージに同封され、メッセージパッケージ通信プロトコルエンベロープに同封される

JAXM を使って SOAP メッセージを構築するとき、どちらのモデルを採用するかを指定する必要はありません。添付ファイルを追加すると、図 5-4 のようなメッセージが構築されます。追加しない場合は、図 5-3 のようなメッセージが構築されます。

図 5-4 は、添付ファイル付きの SOAP メッセージを示します。添付ファイルの部分には、イメージファイル、プレーンテキストなどどのような種類のコンテンツでも含めることができます。メッセージの送信元は、添付ファイル付きの SOAP メッセージを作成するかどうかを指定できます。メッセージの受信先も、添付ファイルをコンシュームするかどうかを指定できます。

1 つまたは複数の添付ファイルを含むメッセージは、メッセージのすべての部分を含む MIME エンベロープに同封されます。JAXM では、クライアントが添付ファイル部分を作成すると、MIME エンベロープが自動的に生成されます。メッセージに添付ファイルを追加した場合、MIME ヘッダーに、その添付ファイル内のデータのタイプを指定する必要があります。

図 5-4    添付ファイル付き SOAP メッセージ
図は、SOAP 添付ファイルを含む添付ファイル部分が MIME エンベロープに同封された SOAP 部分 (エンベロープのヘッダーおよび本体を含む) を示す。



Java での SOAP メッセージング



SOAP 仕様には、プログラミングモデルや SOAP メッセージを構築するための API は定義されていません。SOAP メッセージのパッケージ化に使用できる XML スキーマが定義されているだけです。

JAXM は、アプリケーションプログラミングインタフェースの 1 つです。JAXM を実装することにより、SOAP メッセージングのプログラミングモデルをサポートできます。また、SOAP メッセージの構築、送受信、確認のためにアプリケーションやツールの作成者が使用する Java オブジェクトを供給することができます。JAXM は、次の 2 つのパッケージを定義します。

  • javax.xml.soap: このパッケージのオブジェクトを使って、SOAP メッセージの各部分を定義したり、SOAP メッセージのアセンブルや逆アセンブルを行うことができます。プロバイダのサポートなしでも、このパッケージを使って SOAP メッセージを送信できます。

  • javax.xml.messaging: このパッケージのオブジェクトでは、プロバイダを使って SOAP メッセージを送信したり、SOAP メッセージを受信したりできます。

この章では、次の操作を行うために、javax.xml.soap パッケージとこれによって定義されているオブジェクトおよびメソッドの使用方法について説明します。

  • SOAP メッセージのアセンブルおよび逆アセンブル

  • SOAP メッセージの送受信

また、JMS API と MQ を使って SOAP メッセージペイロードを伝送する JMS メッセージを送受信する方法についても説明します。


SOAP メッセージオブジェクト

図 5-5 に示すように、SOAP メッセージオブジェクトはオブジェクトツリーを形成します。javax.xml.soap パッケージには、ツリーオブジェクトの派生元となるクラスやインタフェースがすべて定義されています。

図 5-5    SOAP メッセージオブジェクト
図は、SOAP メッセージオブジェクトを構成するオブジェクトの階層を示す。 図の後に長い説明がある

[D]

上図に示されるように、SOAPMessage オブジェクトはSOAP 部分と添付ファイル部分の 2 つの部分に分けられるオブジェクトのコネクションです。重要なことは、添付ファイル部分に XML 以外のデータが含まれている可能性があることです。

メッセージの SOAP 部分のエンベロープには、本体 (データや障害情報を含む) とオプションのヘッダーが含まれています。JAXM を使って SOAP メッセージを作成すると、本体要素だけを作成する必要がある場合でも、SOAP 部分、エンベロープ、および本体が作成されます。このためには、本体要素の親、つまり SOAP 本体を取得する必要があります。

SOAPMessage ツリー内のオブジェクトに移動するには、次のコードに示されるように、ルートからツリー内を移動していく必要があります。たとえば、SOAPMessage MyMsg を作成したとします。この場合、次のような呼び出しで SOAP 本体を取得できます。

SOAPPart MyPart = MyMsg.getSOAPPart();

SOAPEnvelope MyEnv = MyPart.getEnvelope();

SOAPBody MyBody = envelope.getBody();

ここで、本体要素の名前を作成し (「ネームスペース」を参照)、SOAPMessage に本体要素を追加します。

たとえば、次のコードで本体要素の名前 (XML タグ表現) を作成します。

Name bodyName = envelope.createName("Temperature");

次のコードで本体要素を本体に追加します。

SOAPBodyElement myTemp = MyBody.addBodyElement(bodyName);

最後に、次のコードで本体要素 bodyName のデータを定義します。

myTemp.addTextNode("98.6");


継承されたメソッド

SOAP メッセージの要素はツリーを形成します。ツリー内の各ノードは Node インタフェースを実装します。エンベロープレベルから始まる各ノードは、さらに SOAPElement インタフェースも実装します。その結果、表 5-1 のような共有メソッドが得られます。


表 5-1    継承されたメソッド 

継承元

メソッド名

用途

SOAPElement
 
addAttribute(Name, String)
 

特定の Name オブジェクトと文字列値を持つ属性を追加する  

 

addChildElement(Name)

addChildElement(String, String)

addChildElement(String, String, String)  

指定の Name オブジェクトで初期化された新しい SOAPElement オブジェクトを作成し、追加する

(Name オブジェクトの作成には Envelope.createName メソッドを使用)  

 

addNameSpaceDeclaration (String, String)
 

特定のプレフィックスおよび URI を持つネームスペース宣言を追加する  

 

addTextnode(String)
 

指定の String で初期化された新しい Text オブジェクトを作成し、この SOAPElement オブジェクトに追加する  

 

getAllAttributes()
 

このオブジェクト内のすべての属性名に反復子を返す  

 

getAttributeValue(Name)
 

特定の属性の値を返す  

 

getChildElements()
 

この要素の直系のコンテンツすべてに反復子を返す  

 

getChildElements(Name)
 

特定の名前の子要素すべてに反復子を返す  

 

getElementName()
 

このオブジェクトの名前を返す  

 

getEncodingStyle()
 

このオブジェクトのコード化形式を返す  

 

getNameSpacePrefixes()
 

ネームスペースプレフィックスの反復子を返す  

 

getNamespaceURI(String)
 

特定のプレフィックスを持つネームスペースの URI を返す  

 

removeAttribute(Name)
 

特定の属性を削除する  

 

removeNamespaceDeclaration
(String)

 

特定のプレフィックスに対応するネームスペース宣言を削除する  

 

setEncodingStyle(String)
 

このオブジェクトのコード化形式を String によって指定されたコード化形式に設定する  

Node
 
detachNode()
 

ツリーからこの Node オブジェクトを削除する  

 

getParentElement()
 

この Node オブジェクトの親要素を返す  

 

getValue
 

この Node オブジェクトの直接の子の値を返す。ただし、子要素が存在し、その値が text である場合  

 

recycleNode()
 

この Node オブジェクトがもう使用されておらず、再利用できることを実装に通知する  

 

setParentElement
(SOAPElement)
 

このオブジェクトの親を SOAPElement パラメータによって指定された親に設定する  


ネームスペース

XML ネームスペースでは、要素名や属性名を同じドキュメント内のその他の名前と区別できます。この節では、XML ネームスペースの概要と SOAP での使用方法を簡単に説明します。詳細は、 http://www.w3.org/TR/REC-xml-names/ を参照してください。

明示的な XML のネームスペース宣言は、次の形式をとります。

<prefix:myElement

xmlns:prefix ="URI">

この宣言は、prefix を特定の URI の別名として定義します。myElement 内で prefix と任意の要素または属性を使って、この要素名または属性名が URI で指定されたネームスペースに属するように指定できます。

次に、ネームスペース宣言の例を示します。

<SOAP-ENV: Envelope

xmlns: SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"

この宣言は、ネームスペースの別名として SOAP_ENV を定義します。

http://schemas.xmlsoap.org/soap/envelope/

定義済みの別名は、Envelope 要素内の任意の属性または要素のプレフィックスとして使用できます。コード例 5-1 では、要素 <Envelope><Body> および属性 encodingStyle は、すべて URI "http://schemas.xmlsoap.org/soap/envelope/" で指定された SOAP ネームスペースに属します。

コード例 5-1    明示的なネームスペース宣言 

<SOAP-ENV:Envelope
   xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
   SOAP-ENV:encodingStyle=
                     "http://schemas.xmlsoap.org/soap/encoding/">

   <SOAP-ENV:Header>
        <HeaderA
xmlns="HeaderURI"
SOAP-ENV:mustUnderstand="0">
     ヘッダーのテキスト
     </HeaderA>
</SOAP-ENV:Header>
   <SOAP-ENV:Body>
.
.
.
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

ネームスペースを定義する URI が実際の場所をポイントしている必要はありません。URI の目的は、属性名と要素名を区別することです。


事前定義済みの SOAP ネームスペース
SOAP には、次の 2 つのネームスペースが定義されています。

  • 次のネームスペース識別子を持つ SOAP エンベロープ (SOAP メッセージのルート要素)

    "http://schemas.xmlsoap.org/soap/envelope"

  • 次のネームスペース識別子を持つ SOAP 直列化 (SOAP の直列化の規則を定義する URI)

    "http://schemas.xmlsoap.org/soap/encoding"

JAXM を使ってメッセージを構築またはコンシュームする場合は、ネームスペースの設定および処理を正しく行い、不正なネームスペースを持つメッセージを破棄する必要があります。


ネームスペースによる SOAP 名の作成
SOAP メッセージの本体要素やヘッダー要素を作成するときは、Name オブジェクトを使って、その要素に適した名前を指定する必要があります。Name オブジェクトは、SOAPEnvelope.createName メソッドを呼び出すことで取得できます。

このメソッドを呼び出すとき、パラメータとしてローカル名を指定するか、またはローカル名、プレフィックス、URI を指定できます。たとえば、次のコードは Name オブジェクト bodyName を定義します。

Name bodyName = MyEnvelope.createName("TradePrice",
                                 "GetLTP",
                                 "http://foo.eztrade.com");

これは、次のネームスペース宣言と同等です。

<GetLTP:TradePrice xmlns:GetLTP= "http://foo.eztrade.com">

次のコードでは、名前を作成し、SOAPBody 要素と関連付ける方法を示します。createName メソッドの使用方法と配置に注目してください。

SoapBody body = envelope.getBody(); //get body from envelope

Name bodyName = MyEnvelope.createName("TradePrice",
                                "http://foo.eztrade.com");

SOAPBodyElement gltp = body.addBodyElement(bodyName);


Name オブジェクトのパース
特定の Name オブジェクトの名前をパースするときは、次の Name メソッドを使用して名前をパースします。

  • getQualifiedName は「prefix:LocalName」を返す。特定の名前を使用する場合、GetLTP:TradePrice を返す

  • getURI"http://foo.eztrade.com" を返す

  • getLocalName は「TradePrice」を返す

  • getPrefix は「GetLTP」を返す


送信先、メッセージファクトリ、コネクションオブジェクト

SOAP メッセージングは、メッセージファクトリによって作成された SOAP メッセージがコネクションを介してエンドポイントに送信されるとき行われます。

  • プロバイダを使用しない場合は、次の作業を行う必要があります。

    • SOAPConnectionFactory オブジェクトの作成

    • SOAPConnection オブジェクトの作成

    • メッセージの送信先を表す Endpoint オブジェクトの作成

    • MessageFactory オブジェクトの作成と、このオブジェクトによるメッセージの作成

    • メッセージの生成

    • メッセージの送信

  • プロバイダを使用する場合は、次の作業を行う必要があります。

    • ProviderConnectionFactory オブジェクトの作成

    • プロバイダコネクションファクトリからの ProviderConnection オブジェクトの取得

    • プロバイダコネクションからの MessageFactory オブジェクトの取得と、このオブジェクトによるメッセージの作成

    • メッセージの生成

    • メッセージの送信

次の 3 つの項では、エンドポイント、メッセージファクトリ、コネクションオブジェクトについて詳しく説明します。


エンドポイント

エンドポイントは、メッセージの最終的な送信先を表します。エンドポイントは、プロバイダを使用する場合 Endpoint クラス、使用しない場合 URLEndpoint クラスによって定義されます。


エンドポイントの構築
エンドポイントを初期化するときは、そのコンストラクタを呼び出すか、ネーミングサービス内でエンドポイントを検索します。エンドポイント用の管理対象オブジェクトの作成方法については、「JAXM 管理対象オブジェクトの使用」を参照してください。

次のコードでは、コンストラクタを使って URLEndpoint を作成します。

myEndpoint = new URLEndpoint("http://somehost/myServlet");


エンドポイントによるメッセージのアドレス指定
プロバイダを使用する場合、メッセージを作成するメッセージファクトリにより、メッセージヘッダー内にエンドポイントが指定されます。

プロバイダを使用しない場合、SOAP メッセージの送信に使用する SOAPConnection.call メソッドのパラメータとしてエンドポイントを指定できます。


複数のエンドポイントへのメッセージ送信
管理対象オブジェクトを使ってエンドポイントを定義する場合は、その管理対象オブジェクトと複数の URL を関連付けることができます。この場合、各 URL が着信 SOAP メッセージを処理することができます。次のサンプルコードは、検索名が myEndpoint というエンドポイントと 2 つの URL (http://www.myServlet1/ および http://www.myServlet2/) を関連付けています。


imqobjmgr add
    -t e
    -l "cn=myEndpoint"
    -o "imqSOAPEndpointList=http://www.myServlet1/
                    http://www.myServlet2/"


この構文により、SOAP コネクションを使って複数のエンドポイントに SOAP メッセージをパブリッシュできます。エンドポイント管理対象オブジェクトの詳細は、「JAXM 管理対象オブジェクトの使用」を参照してください。


メッセージファクトリ

メッセージファクトリを使って SOAP メッセージを作成できます。

  • プロバイダを使用する場合は、プロバイダコネクションの createMessageFactory メソッドを使ってメッセージファクトリを作成します。たとえば、プロバイダコネクションが con の場合、次のコードでメッセージファクトリ mf を作成できます。

    MessageFactory mf = con.createMessageFactory(xProfile);

    createMessageFactory メソッドに profile パラメータを指定することにより、メッセージファクトリによって作成されたメッセージのヘッダーに配置するアドレス指定やその他の情報を決定します。

  • プロバイダを使用しない場合は、次のようにメッセージファクトリを直接インスタンス化します。

    MessageFactory mf = MessageFactory.newInstance();


コネクション

JAXM を使って SOAP メッセージを送信する場合は、SOAPConnection または ProviderConnection を取得する必要があります。さらに、MQ を使って SOAP メッセージを転送することもできます。詳細は、「SOAP と MQ の統合」を参照してください。


SOAP コネクション
SOAPConnection では、リモートロケーションにメッセージを直接送信できます。SOAPConnection オブジェクトを取得するには、単に静的メソッド SOAPConnectionFactory.newInstance() を呼び出します。このタイプのコネクションでは、信頼性も安全性も保証されません。


プロバイダコネクション
ProviderConnectionFactory から取得した ProviderConnection を使って、特定のメッセージングプロバイダへのコネクションを作成します。プロバイダを使って SOAP メッセージを送信する場合、このメッセージはプロバイダに転送されます。このメッセージは、プロバイダによって最終的な送信先に配信されます。プロバイダは信頼性の高い、安全なメッセージングを保証します。現在、MQ は SOAP プロバイダサポートを提供していません。



JAXM 管理対象オブジェクトの使用



管理対象オブジェクトは、プロバイダ固有の設定およびネーミング情報をカプセル化するオブジェクトです。エンドポイントオブジェクトの場合、このようなオブジェクトをインスタンス化するか、管理対象オブジェクトを作成してエンドポイントオブジェクトのインスタンスに関連付けることができます。

JNDI 検索でエンドポイントを作成する方法には、コードからエンドポイントの URL を切り離すことができるという利点があります。この場合、アプリケーションは、コードの再コンパイルなしで送信先を変更できます。さらに、プロバイダへの非依存性という利点も得られます。

SOAP 要素の管理対象オブジェクトの作成方法は、MQ 内で管理対象オブジェクトを作成する方法と同じです。具体的には、オブジェクトマネージャ (imqobjmgr) ユーティリティを使ってオブジェクトの検索名、属性、タイプを指定します。

エンドポイント管理対象オブジェクトの作成時に指定する必要がある属性やその他の情報は、表 5-2 のとおりです。すべての属性を文字列として指定してください。


表 5-2    SOAP 管理対象オブジェクトに関する情報 

オプション

説明

-o "attribute=val"  

次に示す 3 つのエンドポイント管理対象オブジェクトの属性を指定するオプション

  • URL のリスト

    -o "imqSOAPEndpointList = "url1 url2 ....urln"

    このリストには、スペースで区切られた 1 つまたは複数の URL が含まれる。複数の URL が含まれる場合は、メッセージはすべての URL にブロードキャストされる。各 URL を、SOAP メッセージの受信と処理が可能なサーブレットに関連付ける

  • 名前

    -o "imqSOAPEndpointName=SomeName"

    名前を指定しない場合、デフォルトで Untitled_Endpoint_Object が使用される

  • 説明

    -o "imqSOAPEndpointDescription=my endpoints for broadcast"

    説明を指定しない場合、デフォルト値 "A description for the endpoint object" が指定される

 

-l "cn=lookupName"  

エンドポイントの検索名を指定するオプション  

-t type  

オブジェクトのタイプを指定するオプション。エンドポイントの場合、常に e  

-i filename  

imqobjmgr コマンドが記述されている入力ファイルの名前を指定するオプション。通常、このような入力ファイルは、オブジェクトストア属性の指定に使用される  

-j "attribute=val"  

オブジェクトストア属性を指定するオプション。入力ファイル内にも指定できる。入力ファイルの指定には、-i オプションを使用する  

コード例 5-2 では、imqobjmgr コマンドを使ってエンドポイントの管理対象オブジェクトを作成し、オブジェクトストアに追加する方法を示します。-i オプションで、オブジェクトストア属性 (-j オプション) を定義する入力ファイル名を指定します。

コード例 5-2    エンドポイント管理対象オブジェクトの追加

imgobjmgr add
    -t ep
    -l "cn=myEndpoint"
    -o "imqSOAPEndpointList=http://www.myServlet/
                     http://www.myServlet2/"

    -o "imqSOAPEndpointName=MyBroadcastEndpoint"
    -i MyObjStoreAttrs

管理対象オブジェクトを作成してオブジェクトストアに追加しておけば、JAXM アプリケーション内でエンドポイントを使用するとき、この管理対象オブジェクトを使用できます。コード例 5-3 では、JNDI 検索の初期コンテキストを作成してから、必要なオブジェクトを検索します。

コード例 5-3    エンドポイント管理対象オブジェクトの検索 

Hashtable env = new Hashtable();
env.put (Context.INITIAL_CONTEXT_FACTORY,
    "com.sun.jndi.fscontext.RefFSContextFactory");
env.put (Context.PROVIDER_URL,
    "file:///c:/imq_admin_objects");

Context ctx = new InitialContext(env);
Endpoint mySOAPEndpoint = (Endpoint)
     ctx.lookup("cn=myEndpoint");


管理対象オブジェクトの一覧表示、削除、更新も可能です。詳細は、『MQ 管理者ガイド』を参照してください。



SOAP メッセージングモデルと例



この節では、JAXM を使って SOAP メッセージを送受信する方法を説明します。JAXM を使って SOAP メッセージを構築し、JMS メッセージのペイロードとして送信することもできます。詳細は、「SOAP と MQ の統合」を参照してください。

JAXM は、SOAP メッセージングの実行に使用できる 2 つのモデルを提供します。1 つは SOAPConnection オブジェクトを使用し、1 つは ProviderConnection オブジェクトを使用します。現在、MQ は ProviderConnection オブジェクトをサポートしていません。


SOAP メッセージングプログラミングモデル

この項では、JAXM を使った SOAP メッセージングで使用するプログラミングモデルの概要を説明します。

SOAP メッセージは、コネクションを経由してエンドポイントへ送信されます。コネクションには、ポイントツーポイントコネクション (SOAPConnection クラスによって実装される) とプロバイダコネクション (ProviderConnection クラスによって実装される) の 2 種類があります。


ポイントツーポイントコネクション

ポイントツーポイントコネクションを使って、要求 - 応答メッセージングモデルを確立します。要求 - 応答モデルは 図 5-6 に示すとおりです。

図 5-6    要求 - 応答メッセージング
図は、クライアントがエンドポイントにメッセージを送信し、エンドポイントが受信、処理を行い、送信元に返信するプロセスを示す。

このモデルを使って、クライアントは次の処理を実行できます。

  • エンドポイントを作成して、メッセージを送信する SOAPConnection.call メソッドに渡される URL を指定する

    エンドポイントのさまざまな作成方法については、「エンドポイント」を参照

  • SOAPConnection ファクトリを作成し、SOAP コネクションを取得する

  • メッセージファクトリを作成し、これを使って SOAP メッセージを作成する

  • メッセージのコンテンツ名を作成し、メッセージにコンテンツを追加する

  • SOAPConnection.call メソッドを使ってメッセージを送信する

クライアントは、呼び出しメソッドから返される SOAPMessage オブジェクトを無視します。このオブジェクトはクライアントのブロックを解除するために返されるだけです。

要求- 応答メッセージを待機する JAXM サービスは ReqRespListener オブジェクトを使ってメッセージを受信します。

ポイントツーポイントメッセージングを行うクライアントの詳しい例については、「SOAP クライアントの作成」を参照してください。


プロバイダコネクション

プロバイダコネクションを使って、単方向メッセージングを実装できます。単方向メッセージングモデルの仕組みは 図 5-7 に示すとおりです。

図 5-7    単方向メッセージング
図は、メッセージングプロバイダを経由して SOAP エンドポイントに送信される SOAP メッセージを示す。

ポイントツーポイントモデルとは対照的に、メッセージの最終的な送信先はプロバイダによってメッセージヘッダー内に記述されます。(管理者がメッセージングプロバイダを構成する場合は、Endpoint オブジェクトのリストを提供できます。クライアントがプロバイダを使ってメッセージを送信する場合は、プロバイダはメッセージングプロバイダの Endpoint オブジェクトに記載された送信先に対してのみメッセージを送信します。)

プロバイダコネクション経由で送信されるメッセージは、常にプロバイダ内の中間送信先を経て最終的な送信先に転送されます。プロバイダは、転送の信頼性とメッセージの機密性に対しても責任を負います。

このモデルを使って、クライアントは次の処理を実行できます。

  • プロバイダコネクションファクトリを作成してコネクションを取得する

  • メッセージファクトリを作成して新しいメッセージを作成する

  • コンテンツ名を作成してコンテンツをメッセージに追加する

  • メッセージを送信する。送信メソッドは非同期方式であり、即座に返信する

単方向メッセージを待機する JAXM サービスは、OnewayListener オブジェクトを使って非同期方式でメッセージを受信します。


添付ファイルの操作

メッセージに XML 以外のデータを含める場合は、添付ファイルとして追加する必要があります。1 つのメッセージに任意の数の添付ファイル部分を追加できます。添付ファイル部分の内容は、プレーンテキストからイメージファイルまで多岐にわたります。

添付ファイルを作成するには、URL オブジェクトを作成して、SOAP メッセージに添付するファイルの場所を指定します。さらに、添付ファイル内のデータを解釈するためのデータハンドラを作成します。最後に、添付ファイルを SOAP メッセージに追加します。

添付ファイル部分を作成し、メッセージに追加するには、JavaBeans Activation Framework (JAF) API を使用する必要があります。この API では、データの任意の部分のタイプを判断し、そのアクセスをカプセル化できます。また、使用可能な操作を検出して、この操作を実行する Beans をアクティブ化することもできます。JavaBeans Activation Framework を使用するためには、クライアントコードに activation.jar ライブラリを追加する必要があります。


添付ファイルを作成し、追加するには

  1. URL オブジェクトを作成し、初期化して、SOAP メッセージに添付するファイルの場所を追加します。

    URL url = new URL("http://wombats.com/img.jpg");

  2. データハンドラを作成し、デフォルトハンドラで初期化して、ハンドラのデータソースの場所を表す URL を渡します。

    DataHandler dh = new DataHandler(url);

  3. 添付ファイル部分を作成し、イメージの URL を含むデータハンドラで初期化します。

    AttachmentPart ap1 = message.createAttachmentPart(dh);

  4. 添付ファイル部分を SOAP メッセージに追加します。

    myMessage.addAttachmentPart(ap1);

添付ファイルを作成し、メッセージに追加したあとは、通常どおりメッセージを送信できます。

JMS を使ってメッセージを送信する場合は、SOAPMessageIntoJMSMessage 変換ユーティリティを使って、添付ファイル付きの SOAP メッセージを JMS メッセージに変換できます。その後、MQ を使って、このメッセージをトピックの JMS キューに送信できます。


例外および障害処理

SOAP アプリケーションは、SOAP 例外と SOAP 障害の 2 種類のエラー報告メカニズムを使用できます。

  • SOAP 例外では、SOAP 要求の生成時や応答の非整列化時にクライアントサイドで発生したエラーを処理できます。

  • SOAP 障害では、要求の非整列化時、メッセージの処理時、応答の整列化時にサーバサイドで発生したエラーを処理できます。こうしたエラーに対して、サーバサイドのコードは、本体要素ではなく障害要素を含む SOAP メッセージを作成し、このメッセージをその送信元へ送信する必要があります。メッセージの受信側がメッセージの最終的な送信先ではない場合は、受信側自体を soapactor として特定し、メッセージの送信側がエラーの発生場所を特定できるようにします。詳細は、「SOAP 障害の処理」を参照してください。


SOAP クライアントの作成

ポイントツーポイントメッセージングの SOAP クライアントを作成するには、次の手順に従って呼び出しを行います。

  1. SOAPConnectionFactory のインスタンスを取得します。

    SOAPConnectionFactory myFct = SOAPConnectionFactory.newInstance();

  2. SOAPConnectionFactory オブジェクトから SOAP コネクションを取得します。

    SOAPConnection myCon = myFct.createConnection();

    myCon オブジェクトが返されます。このオブジェクトは、メッセージの送信に使用されます。

  3. メッセージの作成に使用する MessageFactory オブジェクトを取得します。

    MessageFactory myMsgFct = MessageFactory.newInstance();

  4. メッセージファクトリを使ってメッセージを作成します。

    SOAPMessage message = myMsgFct.createMessage();

    作成されたメッセージには、次の図に示す部分がすべて含まれます。


    図は、初期化済みオブジェクト (部分、エンベロープ、ヘッダー、および本体) を持つ SOAP メッセージを示す

    この時点では、メッセージのコンテンツはありません。コンテンツを追加するには、SOAP 本体要素を作成し、その名前とコンテンツを定義して、SOAP 本体に追加する必要があります。

    メッセージの各部分にアクセスするには、親要素上で get メソッドを呼び出して子要素を取得することにより、ツリー内を移動する必要があります。たとえば、SOAP 本体に移動するには、SOAP 部分と SOAP エンベロープを取得することから開始します。

    SOAPPart mySPart = message.getSOAPPart();

    SOAPEnvelope myEnvp = mySPart.getEnvelope();

  5. ここで myEnvp オブジェクトから本体要素を取得できます。

    SOAPBody body = myEnvp.getBody();

    本体要素に追加した子要素はメッセージのコンテンツを定義します。同じようにヘッダーに SOAP コンテンツを追加できます。

  6. SOAP 本体 (またはヘッダー) に要素を追加するときは、まず envelope.createName メソッドを呼び出し、その要素の名前を作成します。このメソッドが返す Name オブジェクトを、本体要素 (またはヘッダー要素) を作成するメソッドにパラメータとして渡します。

    Name bodyName = envelope.createName("GetLastTradePrice", "m",
                                        "http://eztrade.com")

    SOAPBodyElement gltp = body.addBodyElement(bodyName);

  7. ここで、gltp 要素に追加するもう一つの本体要素を作成します。

    Name myContent = envelope.createName("symbol");

    SOAPElement mySymbol = gltp.addChildElement(myContent);

  8. これで、本体要素 mySymbol のデータを定義できるようになります。

    mySymbol.addTextNode("SUNW");

    生成される SOAP メッセージオブジェクトは、次の XML スキーマと同等になります。


    <SOAP-ENV:Envelope
      xmlns:SOAPENV="http://schemas.xmlsoap.org/soap/envelope/">
        <SOAP-ENV:Body>
          <m:GetLastTradePrice xmlns:m="http://eztrade.com">
            <symbol>SUNW</symbol>
          </m:GetLastTradePrice>
      </SOAP-ENV:Body>
    </SOAP-ENV:Envelope>

  9. メッセージを送信したり、メッセージに書き込みを加えたりするたびに、その内容が自動保存されます。ただし、受信済みのメッセージや送信済みのメッセージに変更を加えた場合は、その内容をすべて保存して、手作業でメッセージを更新する必要があります。たとえば、次のように指定します。

    message.saveChanges();

  10. メッセージを送信する前に、送信先エンドポイントの URL を持つ URLEndpoint オブジェクトを作成する必要があります。ただし、メッセージヘッダーにアドレス指定情報を追加するようなプロファイルを使用する場合、この処理は不要です。

    URLEndpoint endPt = new
                         URLEndpoint("http://eztrade.com//quotes");

  11. ここで、メッセージを送信できます。

    SOAPMessage reply = myCon.call(message, endPt);

    同じコネクションで、リプライメッセージ (reply) が受信されます。

  12. 最後に、不要な SOAPConnection オブジェクトを終了します。

    myCon.close();


SOAP サービスの作成

SOAP サービスは、SOAP メッセージの最終的な送信先になります。現時点では、サーブレットとして実装する必要があります。独自のサーブレットを作成できますが、必要に応じて、soap.messaging パッケージ内に提供される JAXMServlet クラスを拡張することもできます。この項では、JAXMServlet クラスを使って SOAP サービスを作成する方法を説明します。

サーブレットは、ReqRespListener インタフェースか OneWayListener インタフェースを実装する必要があります。ReqRespListener が応答を要求するという点を除けば、2 つのインタフェースは同じです。

どちらのインタフェースを使用する場合でも、onMessage(SOAPMsg) メソッドを実装する必要があります。JAXMservlet は、HTTP POST メソッドでメッセージを受信したあと、onMessage を呼び出します。この場合、着信メッセージを SOAP メッセージに変換する doPost() メソッドを実装する必要はありません。

コード例 5-4 は、JAXM サーブレットユーティリティクラスを使用する SOAP サービスの基本構造です。

コード例 5-4    メッセージコンシューマのスケルトン

public class MyServlet extends JAXMServlet implements
                  ReqRespListener

{
  public SOAPMessage onMessage(SOAP Message msg)
  { // 処理メッセージ
  }

コード例 5-5 は、簡単な ping メッセージサービスの例です。

コード例 5-5    簡単な ping メッセージサービス 

public class SOAPEchoServlet extends JAXMServlet
                  implements ReqRespListener{


  public SOAPMessage onMessage(SOAPMessage mySoapMessage) {
  return mySoapMessage
  }
}

表 5-3 では、JAXM サーブレットが使用するメソッドについて説明します。独自のサーブレットを作成する場合は、同様の処理を行うメソッドを用意する必要があります。JAXMServlet を拡張する場合は、Init メソッドと SetMessageFactory メソッドをオーバーライドして、onMessage メソッドを実装しなければなりません。


表 5-3    JAXMServlet メソッド 

メソッド

説明

void init
(ServletConfig)

 

ServletConfig オブジェクトを親オブジェクトのコンストラクタに渡し、デフォルトの messageFactory オブジェクトを作成する

特定のプロファイルに従って着信メッセージを構築したい場合は、SetMessageFactory メソッドを呼び出して、SOAP メッセージの構築時に使用されるプロファイルを指定する必要がある  

void doPost (HTTPRequest, HTTPResponse
 

HTTP 要求の本体を取得し、デフォルトまたは特定の MessageFactory プロファイルに従って SOAP メッセージを作成する

SOAP メッセージをパラメータとして渡して、適切なリスナーの onMessage() メソッドを呼び出す

このメソッドはオバーライドしないようにする  

void setMessageFactory (MessageFactory)
 

MessageFactory オブジェクトを設定する。このオブジェクトを使って、onMessage メソッドに渡される SOAP メッセージを作成する  

MimeHeaders getHeaders (HTTPRequest)
 

特定の HTTPRequest オブジェクト内にヘッダーを格納する MimeHeaders オブジェクトを返す  

void putHeaders (mimeHeaders, HTTPresponse)
 

特定の HTTPResponse オブジェクトに特定の MimeHeaders オブジェクト内のヘッダーを設定する  

onMessage
(SOAPMesssage)

 

SOAP メッセージの受信時にサーブレットによって呼び出されるユーザ定義のメソッド。通常、このメソッドは、受け取った SOAP メッセージを逆アセンブルし、クライアントに応答を返す必要がある (サーブレットが ReqRespListener インタフェースを実装している場合)  


メッセージの逆アセンブル

onMessage メソッドは、サーブレットから受け取った SOAP メッセージを逆アセンブルし、そのコンテンツを正しく処理する必要があります。メッセージの処理中に問題が発生した場合、サービスは、SOAP 障害オブジェクトを作成し、クライアントに送信する必要があります (詳細は、「SOAP 障害の処理」を参照)。

SOAP メッセージ処理では、本体要素の場所を特定してそのコンテンツを処理するとともに、ヘッダーも操作する必要があります。次のサンプルコードでは、onMessage メソッドの本体に含まれる SOAP メッセージを逆アセンブルします。基本的に、SOAP メッセージの解析には、Document Object Model (DOM) API を使用する必要があります。

DOM API の詳細は、http://xml.coverpages.org/dom.html を参照してください。

コード例 5-6    SOAP メッセージの処理 

  SOAPBody sb = env.getBody();

  // 検索中のXElement に新しい Name オブジェクトを作成
  Name ElName = env.createName("XElement");

  //XElement の名前で子要素を取得
  Iterator it = sb.getChildElements( ElName );

  // 最初に一致した子要素を取得
  //1つしか存在しない

  SOAPBodyElement sbe = (SOAPBodyElement) it.next();

  //XElement の値を取得
  MyValue =   sbe.getValue();
}


添付ファイルの処理

SOAP メッセージには、添付ファイルを付けることができます。添付ファイルの作成および追加方法を示すサンプルコードについては、コード例 5-7 を参照してください。添付ファイルの受信および処理方法を示すサンプルコードについては、コード例 5-8 を参照してください。

添付ファイルの処理には、Java Activation Framework API を使用する必要があります。詳細は、http://java.sun.com/products/javabeans/glasgow/jaf.html を参照してください。


メッセージへの応答

メッセージに応答するときは、サーバサイドでクライアントの役割をします。


SOAP 障害の処理

サーバサイドコードは、SOAP 障害オブジェクトを使って、要求の非整列化時、メッセージの処理時、応答の整列化時にサーバサイドで発生したエラーを処理する必要があります。SOAPFault インタフェースは SOAPBodyElement インタフェースを拡張します。

SOAP メッセージは、サーバサイド上でエラー報告を行う特殊な要素および形式を備えています。要求処理時に発生したエラーを報告するため、SOAP メッセージ本体に SOAP 障害要素が含まれることがあります。SOAPFault オブジェクトを含む SOAP メッセージは、サーバサイドで作成され、サーバからクライアントに返されます。この SOAP メッセージは、メッセージの送信元に対して、予想外の動作をすべて報告します。

図 5-8 に示されるように、SOAP 障害オブジェクトは、SOAP 本体の子オブジェクトとして、SOAP メッセージオブジェクトに含まれています。詳細オブジェクトおよび詳細エントリオブジェクトは、受信済みのメッセージの本体の形式が不正である場合と、受信済みのメッセージの本体に不適切なデータが含まれている場合以外は不要です。この場合、詳細エントリオブジェクトは、不正な形式のデータを説明するために使用されます。

図 5-8    SOAP 障害要素
図は、障害情報を含む SOAP メッセージの階層 (SOAP 部分、エンベロープ、本体、障害、詳細、および詳細エントリ) を上位から下位方向に順に示す。

SOAP 障害要素は、次の 4 つのサブ要素を定義します。

  • faultcode

    エラーを識別するコード (修飾名)。ソフトウェアは、このコードを使って、障害を検出するアルゴリズム的メカニズムを提供します。事前定義済みの障害コードは、表 5-4 のとおりです。この要素は必須要素です。

  • faultstring

    障害コードで検出された障害を説明する文字列。この要素は、人間が理解できる形式でエラーの説明を提供します。この要素は必須要素です。

  • faultactor

    障害のソースを指定する URI。メッセージのパス間で障害の原因となったアクター。メッセージが中間ノードを経由せずに最終的な送信先に送信される場合、この要素は不要です。中間ノードで障害が発生した場合、その障害には faultactor 要素が含まれることになります。

  • detail

    この要素は、本体要素に関連した特殊な情報を伝送します。本体要素のコンテンツが正常に処理されなかった場合に生成されます。つまり、この要素が存在しなければ、クライアントは、本体要素が処理されたと見なします。この要素は不正な形式のペイロード以外のエラーでは不要ですが、クライアントに追加情報を提供するために使用することもできます。


事前定義済みの障害コード
SOAP 仕様には、4 つの事前定義済み faultcode 値が規定されています。これらのネームスペース識別子は、http://schemas.xmlsoap.org/soap/envelope/ です。


表 5-4    SOAP の faultcode 値 

faultcode 名

意味

VersionMismatch
 

処理側が、SOAP エンベロープ要素のネームスペースが無効である、つまり SOAP エンベロープのネームスペースが http://schemas.xmlsoap.org/soap/envelope/ 以外であることを検出した  

MustUnderstand
 

受信側が SOAP ヘッダー要素の直系の子要素を認識しなかった、または適切に処理できなかった。この要素の mustUnderstand 属性の値は 1 (true) に設定されている  

Client
 

メッセージの形式が不正であるか、メッセージに適切な情報が含まれていなかった。たとえば、メッセージに適切な認証情報または支払い情報が含まれていなかった。クライアントは、このコードから、メッセージを再送信する前に変更が必要であると判断する

戻り値としてこのコードが返される場合は、SOAPFault オブジェクトに、不正な形式のメッセージに関する追加情報を提供する detailEntry オブジェクトが含まれていると考えられる  

Server
 

コンテンツとコネクションしていないためメッセージが処理されなかった。たとえば、あるメッセージハンドラがアップストリームの別のメッセージハンドラと通信できなかったため、応答しなかった。または、サーバからアクセスする必要があるデータベースがダウンしている。クライアントは、このエラーから、しばらくしたら転送に成功する可能性があると判断する  

これらの標準障害コードは、障害のクラスを表します。これらのコードは、末尾にピリオドと名前を追加することで拡張できます。たとえば、Server.OutOfMemory コード、Server.Down コードなどと定義できます。


SOAP 障害の定義
JAXM では、SOAPFault オブジェクトのメソッドを使って、faultcodefaultstringfaultactor の値を指定できます。次のコードでは、SOAP 障害オブジェクトを作成し、faultcodefaultstringfaultactor の各属性を設定します。


SOAPFault fault;
reply = factory.createMessage();
envp = reply.getSOAPPart().getEnvelope(true);
someBody = envp.getBody();
fault = someBody.addFault():
fault.setFaultCode("Server");
fault.setFaultString("Some Server Error");
fault.setFaultActor(http://xxx.me.com/list/endpoint.esp/)
reply.saveChanges();

サーバは、サーバエラーが発生した場合、着信 SOAP メッセージへの応答としてこのオブジェクトを返すことができます。

次のサンプルコードは、詳細および詳細エントリオブジェクトを定義する方法を示します。詳細エントリオブジェクトの名前を作成する必要があります。


SOAPFault fault = someBody.addFault();
fault.setFaultCode("Server");
fault.setFaultActor("http://foo.com/uri");
fault.setFaultString ("Unkown error");
Detail myDetail = fault.addDetail();
Name bodyName = envelope.createName("GetLastTradePrice", "m",
    "Someuri")).addTextNode("the message cannot contain
    the string //");

reply.saveChanges();



SOAP と MQ の統合



この節では、SOAP ペイロードを含む JMS メッセージの送受信および処理方法を説明します。

MQ には、JMS API を使って SOAP メッセージを送受信するときに役立つユーティリティが付属しています。このユーティリティでは、MQ の高信頼メッセージングサービスを活用するため、SOAP メッセージを JMS メッセージに変換することができます。さらに、受信側では、JMS メッセージを SOAP メッセージに変換し直し、JAXM API を使って処理することができます。

SOAP ペイロードを含む JMS メッセージを送受信または処理するには、次の処理を行います。

  • com.sun.messaging.xml.MessageTransformer ライブラリをインポートします。このユーティリティのメソッドを使って、SOAP メッセージと JMS メッセージ間の変換を行います。

  • SOAP メッセージを転送する前に、MessageTransformer.SOAPMessageIntoJMSMessage メソッドを呼び出す必要があります。このメソッドは SOAP メッセージを JMS メッセージに変換します。変換後の JMS メッセージを通常の JMS メッセージと同様に送信します。プログラムの簡便化のため、SOAP メッセージの受信専用の送信先を選択しておくことをお勧めします。つまり、SOAP メッセージの送信先となる特定のキューまたはトピックを作成し、この送信先には SOAP メッセージだけを送信するようにします。

    SOAP メッセージを JMS メッセージに変換するときは、次のような呼び出しを行う必要があります。

    Message myMsg= MessageTransformer.SOAPMessageIntoJMSMessage
                           (SOAPMessage, Session);

    Session 引数は、Message をプロデユースする時に使用するセッションを指定します。

  • 受信側では、通常の JMS メッセージの場合と同様にして、SOAP ペイロードを含む JMS メッセージを取得します。その後、MessageTransformer.SOAPMessageFromJMSMessage ユーティリティを使用して SOAP メッセージを抽出し、JAXM を使って SOAP メッセージを逆アセンブルしたあと、その他の処理を行います。たとえば、SOAPMessage を取得する場合は、次のような呼び出しを行います。

    SOAPMessage myMsg=  MessageTransformer.SOAPMessageFromJMSMessage
                             (Message, MessageFactory);

    MessageFactory 引数は、ユーティリティが特定の JMS Message から SOAPMessage を構築するとき使用するメッセージファクトリを指定します。

次に、このプロセスを表す使用例とサンプルコードの例をいくつか紹介します。


例 1 : SOAP 処理の延期

最初の例 (図 5-9) では、着信 SOAP メッセージはサーブレットによって受信されます。SOAP メッセージを受信したサーブレット MyServlet は、MessageTransformer ユーティリティを使って、このメッセージを JMS メッセージに変換し、高い信頼性でアプリケーションに転送します。このアプリケーションは、受信した JMS メッセージを SOAP メッセージに再変換し、SOAP メッセージのコンテンツを処理します。

サーブレットが SOAP メッセージを受信する仕組みについては、「SOAP サービスの作成」を参照してください。

図 5-9    SOAP 処理の延期
図は、SOAP 処理の延期を示す。 図は文字で説明される


SOAP メッセージを JMS メッセージに変換して、JMS メッセージを送信するには

  1. ConnectionFactory オブジェクトをインスタンス化し、その属性を設定します。次に例を示します。

    QueueConnectionFactory myQConnFact =
            new com.sun.messaging.QueueConnectionFactory();

  2. ConnectionFactory オブジェクトを使って Connection オブジェクトを作成します。

    QueueConnection myQConn =
            myQConnFact.createQueueConnection();

  3. Connection オブジェクトを使って Session オブジェクトを作成します。

    QueueSession myQSess = myQConn.createQueueSession(false,
            Session.AUTO_ACKNOWLEDGE);

  4. MQ メッセージサービス内の物理的な送信先に対応する MQ Destination 管理対象オブジェクトをインスタンス化します。この例の場合、管理対象オブジェクトは mySOAPQueue、このオブジェクトが参照する物理的な送信先は myPSOAPQ です。

    Queue mySOAPQueue = new com.sun.messaging.Queue("myPSOAPQ");

  5. MessageTransformer ユーティリティを使って SOAP メッセージを JMS メッセージに変換します。なお、ここでは、MySOAPMsg という名前の SOAP メッセージを使用するものとします。

    Message MyJMS = MessageTransformer.SOAPMessageIntoJMSMessage
                                  (MySOAPMsg, MyQSess);

  6. QueueSender メッセージプロデューサを作成します。

    このメッセージプロデューサは mySOAPQueue に関連付けられており、キュー送信先 myPSOAPQ にメッセージを送信する際使用されます。

    QueueSender myQueueSender = myQSess.createSender(mySOAPQueue);

  7. キューへメッセージを送信します。

    myQueueSender.send(myJMS);


受信した JMS メッセージを SOAP メッセージに変換して処理するには

  1. ConnectionFactory オブジェクトをインスタンス化し、その属性値を設定します。

    QueueConnectioFactory myQConnFact = new
            com.sun.messaging.QueueConnectionFactory();

  2. ConnectionFactory オブジェクトを使って Connection オブジェクトを作成します。

    QueueConnection myQConn = myQConnFact.createQueueConnection();

  3. Connection オブジェクトを使って 1 つまたは複数の Session オブジェクトを作成します。

    QueueSession myRQSess = myQConn.createQueueSession(false,
            session.AUTO_ACKNOWLEDGE);

  4. Destination オブジェクトをインスタンス化し、その名前属性を設定します。

    Queue myRQueue = new com.sun.messaging.Queue("mySOAPQ");

  5. Session オブジェクトと Destination オブジェクトを使って、必要な MessageConsumer オブジェクトを作成します。

    QueueReceiver myQueueReceiver =
       myRQSess.createReceiver(myRQueue);

  6. 必要に応じて、MessageListener オブジェクトをインスタンス化し、MessageConsumer オブジェクトに登録します。

  7. 手順 2 で作成した QueueConnection を起動します。クライアントによるコンシュームのためのメッセージは、確立されているコネクションを必ず経由して配信されます。

    myQConn.start();

  8. キューからメッセージを受信します。

    次のコードは、メッセージの同期コンシュームの例です。

    Message myJMS = myQueueReceiver.receive();

  9. Message Transformer を使って JMS メッセージを SOAP メッセージに再変換します。

    SOAPMessage MySoap =
           MessageTransformer.SOAPMessageFromJMSMessage
             (myJMS, MyMsgFactory);

    MessageFactory 引数に NULL を指定した場合、デフォルトのメッセージファクトリを使って SOAP メッセージが構築されます。

  10. 将来の処理に備えて、SOAP メッセージを逆アセンブルします。詳細は、「SOAP メッセージオブジェクト」を参照してください。


例 2 : SOAP メッセージのパブリッシュ

次の例 (図 5-10) では、着信 SOAP メッセージはサーブレットによって受信されます。サーブレットは、SOAP メッセージを JMS メッセージとしてパッケージ化し、トピックに転送 (高信頼) します。このトピックに加入している各アプリケーションは、JMS メッセージを受信し、SOAP メッセージに再変換して、そのコンテンツを処理します。

図 5-10    SOAP メッセージのパブリッシュ
図は、どのように SOAP メッセージが JMS メッセージに変換され、複数のリスナにパブリッシュされるかを示す。この場合、各リスナは JMS メッセージを SOAP メッセージに変換する

JMS メッセージをキューではなくトピックに送信する点を除けば、この処理は、前の例とまったく同じ方法で行われます。コード例 5-7 に、MQ を使って SOAP メッセージをパブリッシュする例を示します。


サンプルコード

この項では、2 つのサンプルコードを取り上げて説明します。最初に取り上げるのは、SOAP ペイロードを含む JMS メッセージを送信する例です。次に取り上げるのは、JMS/SOAP メッセージを受信し、SOAP メッセージを処理する例です。

コード例 5-7 では、JMS API、JAXM API、JAF API を使って、添付ファイル付きの SOAP メッセージを JMS メッセージのペイロードとして送信します。SendSOAPMessageWithJMS のコードには、次のメソッドが含まれています。

  • init メソッドを呼び出して、メッセージのパブリッシュに必要なすべての JMS オブジェクトを初期化するコンストラクタ

  • SOAP メッセージと添付ファイルを作成し、SOAP メッセージを JMS メッセージに変換して、この JMS メッセージをパブリッシュする send メソッド

  • コネクションを終了する close メソッド

  • send メソッドと close メソッドを呼び出す main メソッド

    コード例 5-7    SOAP ペイロードを持つ JMS メッセージの送信 

    //SOAP メッセージの構築に必要なライブラリ
    import javax.xml.soap.SOAPMessage;
    import javax.xml.soap.SOAPPart;
    import javax.xml.soap.SOAPEnvelope;
    import javax.xml.soap.SOAPBody;
    import javax.xml.soap.SOAPElement;
    import javax.xml.soap.MessageFactory;
    import javax.xml.soap.AttachmentPart;
    import javax.xml.soap.Name

    // 添付ファイルの操作に必要なライブラリ (Java Activation Framework API)
    import java.net.URL;
    import javax.activation.DataHandler;

    //SOAP メッセージを JMS メッセージに変換して送信するために必要なライブラリ
    import com.sun.messaging.xml.MessageTransformer;
    import com.sun.messaging.BasicConnectionFactory;

    //JMS コネクションを設定してメッセージを送信するために必要なライブラリ
    import javax.jms.TopicConnectionFactory;
    import javax.jms.TopicConnection;
    import javax.jms.JMSException;
    import javax.jms.Session;
    import javax.jms.Message;
    import javax.jms.TopicSession;
    import javax.jms.Topic;
    import javax.jms.TopicPublisher;

    //SOAP ペイロードを含む JMS メッセージを送信するクラスを定義する
    public class SendSOAPMessageWithJMS{

      TopicConnectionFactory tcf = null;
      TopicConnection tc = null;
      TopicSession session = null;
      Topic topic = null;
      TopicPublisher publisher = null;

    // デフォルトのコンストラクタメソッド
    public SendSOAPMessageWithJMS(String topicName){
      init(topicName);
      }

    //JMS のコネクション、セッション、トピックおよびパブリッシャを初期化するメソッド
    public void init(String topicName) {
      try {
      tcf = new com.sun.messaging.TopicConnectionFactory();
      tc = tcf.createTopicConnection();
      session = tc.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
      topic = session.createTopic(topicName);
      publisher = session.createPublisher(topic);
      }

    //SOAP/JMS メッセージを作成および送信するメソッド
    public void send() throws Exception{
      MessageFactory mf = MessageFactory.newInstance(); // デフォルトファクトリの作成
      SOAPMessage soapMessage=mfcreateMessage(); //SOAP メッセージオブジェクトの作成
      SOAPPart soapPart = soapMessage.getSOAPPart();// 本体へのドリルダウンの開始
      SOAPEnvelope soapEnvelope = soapPart.getEnvelope(); // 最初にエンベロープ
      SOAPBody soapBody = soapEnvelope.getBody();
      Name myName = soapEnvelope.createName("HelloWorld", "hw",
                       http;//www.sun.com/imq'); // 本体要素の名前

      SOAPElement element = soapBody.addChildElement(myName); // 本体要素を追加
      element.addTextNode("Welcome to SUnOne Web Services."); // テキスト値を追加

      //Java Framework Activation API で添付ファイルを作成する
      URL url = new URL("http://java.sun.com/webservices/");
      DataHandler dh = new DataHnadler (url);
      AttachmentPart ap = soapMessage.createAttachmentPart(dh);

      // コンテンツタイプと ID を設定する
      ap.setContentType("text/html");
      ap.setContentID('cid-001");

      //SOAP メッセージに添付ファイルを追加する
      soapMessage.addAttachmentPart(ap);
      soapMessage.saveChanges();

      //SOAP メッセージを JMS メッセージに変換する
      Message m = MessageTransformer.SOAPMessageIntoJMSMessage(soapMessage,
                       session);


    //JMS メッセージをパブリッシュする
      publisher.publish(m);

    //JMS コネクションを終了する
      public void close() throws JMSException {
      tc.close();
      }

    //SOAP メッセージを JMS で送信するメインプログラム
    public static void main (String[] args) {
      try {
        String topicName = System.getProperty("TopicName");
        if(topicName == null) {
          topicName = "test";
        }

        SendSOAPMEssageWithJMS ssm = new SendSOAPMEssageWithJMS(topicName);
        ssm.send();
        ssm.close();
      }
        catch (Exception e) {
          e.printStackTrace();
        }
      }
    }

コード例 5-8 では、JMS API、JAXM API、DOM API を使って、添付ファイル付きの SOAP メッセージを JMS メッセージのペイロードとして受信します。ReceiveSOAPMessageWithJMS のコードには、次のメソッドが含まれています。

  • init メソッドを呼び出して、メッセージの受信に必要なすべての JMS オブジェクトを初期化するコンストラクタ

  • メッセージを配信し、リスナーに呼び出される onMessage メソッド。onMessage メソッドは、Message Transformer ユーティリティを使用し JMS メッセージを SOAP メッセージに変換し、JAXM API を使って SOAP 本体を処理し、JAXM および DOM API を使ってメッセージの添付ファイルを処理する

  • ReceiveSOAPMessageWithJMS クラスを初期化する main メソッド

    コード例 5-8    SOAP ペイロードを持つ JMS メッセージの受信 

    //SOAP の処理をサポートするライブラリ
    import javax.xml.soap.MessageFactory;
    import javax.xml.soap.SOAPMessage;
    import javax.xml.soap.AttachmentPart

    //JMS から SOAP への transformer を含むライブラリ
    import com.sun.messaging.xml.MessageTransformer;

    //JMS メッセージングサポート用のライブラリ
    import com.sun.messaging.TopicConnectionFactory

    //JMS メッセージング用のインターフェース
    import javax.jms.MessageListener;
    import javax.jms.TopicConnection;
    import javax.jms.TopicSession;
    import javax.jms.Message;
    import javax.jms.Session;
    import javax.jms.Topic;
    import javax.jms.JMSException;
    import javax.jms.TopicSubscriber

    //添付ファイル部分のパースをサポートするライブラリ (DOM API から)
    import java.util.iterator;

    public class ReceiveSOAPMessageWithJMS implements MessageListener{
      TopicConnectionFactory tcf = null;
      TopicConnection tc = null;
      TopicSession session = null;
      Topic topic = null;
      TopicSubscriber subscriber = null;
      MessageFactory messageFactory = null;

    //デフォルトのコンストラクタ
    public ReceiveSOAPMessageWithJMS(String topicName) {
      init(topicName);
    }
    //Set up JMS connection and related objects
    public void init(String topicName){
      try {
        // デフォルトの SOAP メッセージファクトリを構築する
        messageFactory = MessageFactory.newInstance();

        //JMS の設定
        tcf = new. com.sun.messaging.TopicConnectionFactory();
        tc = tcf.createTopicConnection();
        session = tc.createTopicSesstion(false, Session.AUTO_ACKNOWLEDGE);
        topic = session.createTopic(topicName);
        subscriber = session.createSubscriber(topic);
        subscriber.setMessageListener(this);
        tc.start();

        System.out.println("ready to receive SOAP m essages...");
      }catch (Exception jmse){
        jmse.printStackTrace();
        }
      }

    //JMS メッセージが onMessage メソッドに配信される
    public void onMessage(Message message){
      try {
        //JMS メッセージを SOAP メッセージに変換する
        SOAPMessage soapMessage = MessageTransformer.SOAPMessageFromJMSMessage
                  (message, messageFactory);



        // 添付ファイル数を印刷
        System.out.println("message received!Attachment counts:
                  " + soapMessage.countAttachments());


        //SOAP メッセージの添付ファイル部分を取得
        Iterator iterator = soapMessage.getAttachments();
        while (iterator.hasNext()) {
          // 次の添付ファイルを取得
          AttachmentPart ap = (AttachmentPart) iterator.next();

          // コンテンツタイプを取得
          String contentType = ap.getContentType();
          System.out.println("content type:" + conent TYpe);

          // コンテンツ ID を取得
          String contentID = ap.getContentID();
          System.out.println("content Id:"+ contentId);

          // テキストであるかを確認する
          if(contentType.indexOf"text")>=0 {
            // 添付ファイルがテキストであれば文字列のコンテンツを取得して印刷する
            String content = (String) ap.getContent();
            System.outprintln("*** attachment content:" + content);
          }
        }
      }catch (Exception e) {
        e.printStackTrace();
      }
    }

    // 受信先のサンプルを開始するメインメソッド
    public static void main (String[] args){
      try {
        String topicName = System.getProperty("TopicName");
        if( topicName == null) {
          topicName = "test";
        }
        ReceiveSOAPMessageWithJMS rsm = new ReceiveSOAPMessageWithJMS(topicName);
      }catch (Exception e) {
        e.printStackTrace();
        }
      }
    }


前へ      目次      索引      次へ     
Copyright © 2002 Sun Microsystems, Inc. All rights reserved.

最終更新日 2002 年 6 月 19 日