この記事シリーズの第 1 回では、WSDL について説明しました。WSDL は、Web サービスのインターフェースを記述する言語です。Web サービスの所有者は、自分のインターフェースを SOAP を使用して実装します。したがって、WSDL サービス とは、実際には SOAP サービス として存在するといえます。Web サービス利用者は、WSDL ファイルを手にすれば、インターフェースの詳細情報が分かります。そうすれば、SOAP を使用して Web サービスと通信できるようになります。
Web サービスは、WSDL インターフェースを介して公開でき、SOAP を使用してインターネット経由でリモートにアクセスすることのできるオブジェクトであると考えることができます。これらのサービスはオブジェクトですので、各サービスに関連するなんらかのプロパティーと、各サービスを呼び出すための振る舞いがあるはずです。SOAP メッセージは、HTTP で動作する XML 文書です。
企業間取引 (B2B) およびアプリケーション間取引 (A2A) の要件では、企業が情報を交換するために相互に通信し合うことが必要とされます。この概念は、B2B やワークフロー、および企業統合を通じて使用されます。たとえば、ある企業がその顧客の要求を満たすために供給業者のサービスを呼び出す必要があるような、縦方向のサプライ・チェーンの場合を考えてみましょう。一部の供給業者は、サプライ・チェーンをさらに下方にたどって、他の企業のサービスを呼び出さなければならなくなるでしょう。
このようなアプリケーションで最も重視されるのは、いうまでもなく相互運用可能性です。どの企業も、SOAP 通信チャネルのエンドを 1つだけ実装します。インターネット上のどこかに存在する誰か がもう一方のエンドになります。
ここ数年、企業間の統合と相互運用可能性は、ソフトウェア・エンジニアと企業の両者にとって乗り越えるべき課題でした。プラットフォームの依存関係が、統合と相互運用可能性を実現するうえでの大きな問題でした。SOAP こそ、企業間での統合と相互運用可能性を実現するための最もシンプルなメカニズムです。
SOAP とその目的を基本的に理解されたと思われるので、次はその内側に迫るため、SOAP のアーキテクチャーについて解説していきます。図 1 を見てください。典型的な SOAP 通信アーキテクチャーの以下のコンポーネントを確認できます。
- SOAP クライアント
- SOAP サーバー
- 実際のサービス
図 1. 典型的な SOAP 通信アーキテクチャーのコンポーネント
上述のエンティティーそれぞれのアーキテクチャー上の役割を説明しましょう。
以下の説明は図 1 を参照しています。
SOAP クライアントは、SOAP 対応のマシンであり、SOAP 要求を HTTP を介して SOAP サーバー に生成および送信することができます。SOAP 要求は SOAP メッセージの一種です。通常、SOAP メッセージには、SOAP クライアントが SOAP サーバーに送信する SOAP 要求 と、それに応答して SOAP サーバーが SOAP クライアントに送信する SOAP 応答の 2つのタイプしかありません。リスト 1 は、典型的な SOAP 要求です。SOAP 応答は、リスト 2 で参照してください。
リスト 1: 単純な SOAP 要求
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" >
<SOAP-ENV:Body>
<m:getListOfModels xmlns:m = "uri reference" >
</m:getListOfModels>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
|
SOAP サーバーも SOAP 対応のマシンであり、SOAP クライアントからの要求を受け入れ、適切な応答をオーサリングする機能を持っています。このようなエンコードされた応答が要求側の SOAP クライアントに戻ります。SOAP サーバーの内部には、以下の 3つのエンティティーがあります。
- サービス・マネージャー
- 配置済みのサービス・リスト
- XML 変換プログラム
サービス・マネージャーは、要求に対するサービスの管理を受け持ちます。リスト 1 の SOAP 要求をもう一度見てください。要素 <m:getListOfModels xmlns:m="urn:MobilePhoneservice" > に、サービスの名前が入っているのが分かります。サービス・マネージャーは、SOAP クライアントが呼び出したい SOAP サービスの名前を読み取り、必要なサービスが実際にこの SOAP サーバーにあるかどうかをチェックします。そのエンドで、配置済みのサービス・リスト、つまりその SOAP サーバーがホストするすべてのサービスのリストを照会します。そこに必要なサービスがあれば、サーバー・マネージャーは、SOAP 要求を XML 変換プログラムに渡します。XML 変換プログラムは、SOAP 要求の XML 構造を、プログラマーが実際のサービスの実装に使用したプログラム言語 (たとえば、Java プログラム言語) の構造に変換します。また実際のサービスからの応答を、SOAP 応答の XML 構造に変換し直すことも担当します。SOAP 応答を示すリスト 2 を見てください。
リスト 2: 単純な SOAP 応答
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body>
<m:getListOfModelsResponse xmlns:m="urn:MobilePhoneservice">
<Model>M1</Model>
<Model>M2</Model>
<Model>M3</Model>
</m:getPriceResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
|
図 1 の actual service というラベルの付いたボックスは、実際のサービスが常駐するロケーションを表しています。サービスの実装は、たとえば、COM コンポーネントや JavaBeans コンポーネントの形式となります。XML 変換プログラムは、XML 構造を適正なメソッド起動呼び出しに変換します。XML 変換プログラムが実際のサービス実装のなんらかのメソッドを呼び出すと、そのメソッドは自分のジョブを実行して、結果として得られた情報を XML 変換プログラムに返します。
XML 変換プログラムを実際のサービスにつないでいる図 1 の矢印を見てください。この矢印の両端とも同じ企業内にあります。つまり、同じ組織が通信の両端でインターフェースに対する制御を持つということです。この矢印を、SOAP クライアントと SOAP サーバー間にある、企業の境界を超えてつながっている矢印と比較してみてください。これがまさに、SOAP の目的なのです。
SOAP クライアントは、SOAP メッセージを SOAP サーバーに送信するとき、トランスポートのために HTTP プロトコルを使用します。これは、HTTP との SOAP バインディングと呼ばれています。SOAP サーバーは、メッセージを受け取ると、それをサービス・マネージャーに渡します。サービス・マネージャーは、SOAP メッセージ内の必要なサービスを配置済みサービス・リストで調べます。要求されたサービスを見つけることができなければ、SOAP クライアントに要求の失敗を示す応答を返します。しかし、サービスが使用可能な場合は、制御がサービス・マネージャーから XML 変換プログラムに移されます。この変換プログラムが適切な言語変換を実行し、実際のサービス実装にアクセスします。サービスの実装は要求を処理し、結果を XML 変換プログラムに送り返します。XML 変換プログラムはそれを SOAP クライアントが理解できる SOAP 応答 (XML 文書) に変換します。SOAP 応答のトランスポートにも HTTP バインディングが使用されます。
次は、HTTP との SOAP バインディングについて詳しく説明していきます。
SOAP を HTTP とバインドしたり、HTTP 上で SOAP を操作したりする場合、実際には HTTP ヘッダーを SOAP 要求と応答に追加します。リスト 1 が典型的な SOAP 要求の構造であるのに対し、リスト 3、リスト 4、リスト 5、およびリスト 6 は、リスト 1 への HTTP ヘッダーの追加を表す、完全な HTTP 要求です。同様に、リスト 7 は、リスト 2 からの SOAP 応答に対応する完全な HTTP 要求です。
HTTP で SOAP を使用するときは、Content-Type フィールドは必ず text/xml でなければなりません。それでは、リスト 3 からリスト 7 まで詳しく説明してゆきましょう。
SOAP を、HTTP 要求メソッド POST と組み合わせて使用できます。SOAP HTTP 要求を送信するためには、HTTP に SOAPAction ヘッダー・フィールドを用意する必要があります。
SOAPAction では SOAP 要求の意図を指定します。サーバー (HTTP で SOAP 要求メッセージをフィルターに掛けるファイアウォールなど) は、SOAPAction の値を使用して判断を下すことができます。
HTTP クライアントは、SOAP HTTP 要求を出すときにこのヘッダー・フィールドを使用します。SOAPAction は以下のいずれかの値となります :SOAPAction: "URI 参照"
SOAPAction: "ファイル名"
SOAPAction: "
SOAPAction:
リスト 3: SOAPAction ヘッダー・フィールドの URI 参照の例
POST /Vendors HTTP/1.1 Host: www.mobilephoneservice.com Content-Type:"text/xml";Charset="utf-8" Content-Length: nnnn SOAPACtion:"www.mobilephoneservice.com/Vendors/MobilePhoneservice#getListOfModels" <?xml version="1.0"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" > <SOAP-ENV:Body> <m:getListOfModels xmlns:m="urn:MobilePhoneservice" > </m:getListOfModels> </SOAP-ENV:Body> </SOAP-ENV:Envelope> |
リスト 3 では、SOAPAction に以下の URI 参照が含まれています。www.mobilephoneservice.com/Vendors/MobilePhoneservice#getListOfModels
この SOAPAction は 2つのことを表します。1つ目は、特定の SOAP 配置のアドレスです:www.mobilephoneservice.com/Vendors/MobilePhoneservice
2つ目は、必要なメソッドの名前を指定するフラグメント ID (#getListOfModels ) です。
リスト 4: SOAPAction ヘッダー・フィールドのファイル名の例
POST /Vendors HTTP/1.1 Host: www.mobilephoneservice.com Content-Type:"text/xml";Charset="utf-8" Content-Length: nnnn SOAPAction:"MobilePhoneservice#getListOfModels" <?xml version="1.0"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" > <SOAP-ENV:Body> <m:getListOfModels xmlns:m="urn:MobilePhoneservice" > </m:getListOfModels> </SOAP-ENV:Body> </SOAP-ENV:Envelope> |
リスト 4 では、SOAPAction にファイル名 ( MobilePhoneservice#getListOfModels) が含まれています。MobilePhoneservice ファイルは、ホスト URI ( www.mobilephoneservice.com/Vendors) に存在しなければなりません。このホスト URI は、HTTP ヘッダーのホスト・フィールド ( www.mobilephoneservice.com) とフォルダー名/Vendorsとの組み合わせです。
リスト 5: SOAPAction ヘッダーの空ストリングの例
POST /Vendors HTTP/1.1 Host: www.mobilephoneservice.com Content-Type:"text/xml";Charset="utf-8" Content-Length: nnnn SOAPAction:" <?xml version="1.0"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" > <SOAP-ENV:Body> <m:getListOfModels xmlns:m="urn:MobilePhoneservice" > </m:getListOfModels> </SOAP-ENV:Body> </SOAP-ENV:Envelope> |
リスト 5 では、SOAPAction に空ストリング (") が含まれています。空ストリング値は、SOAP の意図がホスト URI (www.mobilephoneservice.com/Vendors) と同じであることを表します。
リスト 6: SOAPAction ヘッダーに値がない場合の例
POST /Vendors HTTP/1.1 Host: www.mobilephoneservice.com Content-Type:"text/xml";Charset="utf-8" Content-Length: nnnn SOAPAction: <?xml version="1.0"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" > <SOAP-ENV:Body> <m:getListOfModels xmlns:m ="urn:MobilePhoneservice" > </m:getListOfModels> </SOAP-ENV:Body> </SOAP-ENV:Envelope> |
リスト 6 では、SOAPAction に値が含まれていません。これは、メッセージの意図に関する情報がないことを表します。
SOAP 応答は、次の 2つのタイプのいずれかです。
- SOAP 結果を作成する、正常終了した SOAP 操作
- 結果として SOAP フォールト・メッセージを出す、正常に終了しなかった SOAP 操作
リスト 7: HTTP ヘッダーを持つ正常終了した SOAP 応答
HTTP/1.1 Content-Type:"text/xml"; Charset="utf-8" Content-Length: nnnn <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" > <SOAP-ENV:Body> <m:getListOfModelsResponse xmlns:m = "URI-Reference"> <model>m1</model> <model>m2</model> </m:getListOfModels> </SOAP-ENV:Body> |
リスト 7 は、SOAP サーバーから意味のある結果を得られた場合の 1つ目の例です。
リスト 8 は、典型的な SOAP フォールト・メッセージです。SOAP HTTP 応答は、HTTP での状況情報の通信に使用される HTTP 状況コードのセマンティクスに従います。要求の処理中に SOAP エラーがあった場合、SOAP HTTP サーバーは、応答の中に SOAP フォールト要素とともに SOAP メッセージを含む、HTTP 500 "Internal Server Error" 応答を出さなければなりません。
リスト 8: HTTP ヘッダーを持つ典型的な SOAP フォールト・メッセージ
HTTP/1.1 500 Internal Server Error Content-Type: "text/xml"; Charset="utf-8" Content-Length: nnnn <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" > <SOAP-ENV:Body> <SOAP-ENV:Fault> <faultstring>Failed to process the request</faultstring> </SOAP-ENV:Fault> </SOAP-ENV:Body> </SOAP-ENV:Envelope> |
HTTP が SOAP メッセージをバインディングするための唯一のソリューションというわけではありません。HTTP が適切ではない場合に、SOAP バインディングに SMTP のような他のメカニズムを使用することも可能です。SOAP を SMTP にバインディングすることで、1 方向のトランスポート経路を確立できます。2つの 1 方向メッセージを使用することで、要求 / 応答通信を確立できます。SMTP で SOAP メッセージを送信するには、以下のステップを実行します。
MIME-Version ヘッダー・フィールドの使用
MIME-Version は、バージョン番号を使用して、異なる MIME バージョンを区別します。これは、メール処理エージェント (POP サーバーなど) が、古いバージョンや新しいバージョンで生成されたメール・メッセージを区別できるようにするためのものです。リスト 9 で、MIME-Version ヘッダー・フィールドの使用例を参照してください。
リスト 9: e-mail での SOAP の例TO: <info@waxsys.com> From: <abc@punjab.com> Reply-To: <abc@punjab.com> Date: SAT, 2 Feb 2002 16:00:00 Message-Id: <4FAB345C8D93E93B7A6E9@punjab.com> MIME-Version: 1.0 Content-Type: text/xml; charset=utf-8 Content-Transfer-Encoding: QUOTED-PRINTABLE <?xml version ="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Body> <prnt:echoString xmlns:prnt="http://waxsys.com"> <msgString>Put your mail Message</msgString> </prnt:echoString> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
Content-Type ヘッダー・フィールドの使用:
Content-Type は、メッセージ本体のデータのタイプを識別するために使用します。SOAP メッセージでは、Content-Type は値 "text/xml" を持つ必要があります。リスト 9 で、Content-Type の使用例を参照してください。
Content-Transfer-Encoding フィールドの使用:
Content-Transfer-Encoding は、転送エンコード方式のタイプを指定する、つまり、転送したいデータが文字形式か、バイナリー形式かを指定するために使用します。リスト 9 では、ASCII 文字セットに従った印刷可能文字に対応する Quoted-Printable エンコード方式を使用しています。この方式では、メール・トランスポート・エージェントが、結果のオクテットを変更しないような方法でデータをエンコードします。リスト 9 で、Content-Transfer-Encoding の使用例を参照してください。
SOAP メッセージとは、オプションの SOAP ヘッダーと必須の SOAP 本体を持つ、必須の SOAP Envelope (エンベロープ) から成る XML 文書のことです。
SOAP スキーマの要素:
- Envelope
- Header
- Body
- Fault
Envelope:
Envelope は、SOAP メッセージを表す一番上の要素です。SOAP メッセージを送信するためには、この要素が存在しなければなりません。Envelope では SOAP ネーム・スペース ID、http://schemas.xmlsoap.org/soap/envelope/ を使用しますが、これは必須です。Envelope に誤ったネーム・スペースが含まれていると、Envelope のネーム・スペースのバージョンに関するエラーが生成されます。リスト 10 は空の Envelope です。これを "空のエンベロープ" と呼び、"ポスト" による送信の前に、最終的には "レター" (おそらく、ビジネス・レター) を含む必要があることを強調します。SOAP スキーマでの "レター" は、"SOAP Body" として参照され、(HTTP との SOAP バインディングのセクションで説明したとおり) HTTP POST がその トランスポート・メカニズムです。
リスト 10: 空の SOAP Envelope
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> </SOAP-ENV:Envelope> |
Header:
SOAP Header はオプションです。SOAP Body を SOAP Envelope の内部に直接ラップし、ヘッダーともどもスキップすることもできます。Header は、SOAP メッセージの機能を拡張するためのメカニズムを提供します。たとえば、SOAP Header エントリーで提供される拡張の一般的な例には認証があります。この場合は下位レベルのトランスポートとして SOAP を使用する認証フレームワークがあります。SOAP でのヘッダーの実装については、リスト 11 を参照してください。
リスト 11: SOAP Envelope での Header の実装
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Header> <m:Order xmlns:m="some URI" SOAP-ENV:mustUnderstand="1"> </m:Order> </SOAP-ENV:Header> </SOAP-ENV:Envelope> |
Body:
Body 要素には、送信する実際のメッセージを含みます。これは必須の要素であり、その子の要素は通常、ユーザー定義のネーム・スペースに属します。リスト 12 は、ユーザー定義のネーム・スペース "u" を参照する SOAP メッセージを示しています。Body 要素は、必須の情報のコンテナーです。この要素は、SOAP メッセージ内に存在し、SOAP Envelope 要素の直接の子要素でなければなりません。また、SOAP Header 要素のすぐ後に続く必要があります。Header 要素が存在しない場合には、Envelope 要素のすぐ後に続く必要があります。本体には子要素を含むことができ、これらの子要素をネーム・スペースで修飾することができます。
リスト 12: SOAP Envelope 内の Header と Body
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Header> <m:Order xmlns:m="some URI" SOAP-ENV:mustUnderstand="1"> </m:Order> </SOAP-ENV:Header> <SOAP-ENV:Body> <u:GetPrice xmlns:u="some URI" > <model>m1</model> </u:GetPrice> </SOAP-ENV:Body> </SOAP-ENV:Envelope> |
Fault:
この要素はエラー・メッセージを示します。この要素は本体の項目として、また Body 要素内に 1回だけ示すことができます。通常、Fault 要素は SOAP 応答メッセージ内で、SOAP 要求になにか問題があったことを示します。
Fault の副要素:
faultcode(フォールトの識別)faultstring(フォールトの記述)faultactor(このフォールトの原因の識別)detail(エラーの詳細。通常はアプリケーション特有のエラーです。つまり、SOAP 要求の本体で使用されたユーザー定義のネーム・スペースに対応します。)
リスト 13 は典型的なフォールト・メッセージです。
リスト 13: アプリケーション・エラー発生時の SOAP Fault の使用
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Header> <m:Order xmlns:m="some URI" SOAP-ENV:mustUnderstand="1"> </m:Order> </SOAP-ENV:Header> <SOAP-ENV:Body> <SOAP-ENV:Fault> <faultcode>SOAP-ENV:Server</faultcode> <faultstring>Not necessary information</faultstring> <detail> <d:faultdetail xmlns:d = "uri-referrence"> <msg> application is not responding properly. </msg> <errorcode>12</errorcode> </d:faultdetail> </detail> </SOAP-ENV:Fault> </SOAP-ENV:Body> </SOAP-ENV:Envelope> |
第 1 回で紹介した WSDL ファイルへの SOAP 要求
SOAP メッセージ (要求と応答) の一般構文を説明しましたので、次は、この記事のシリーズ第 1 回で紹介した、MobilePhoneservice に対する SOAP 要求の開発方法を示しましょう。第 1 回では、MobilPhoneservice を説明する完全な WSDL インターフェースを設計しました。携帯電話会社は、MobilePhoneservice に 2つのメソッド、getListOfModels() と getPrice(modelNumber) を用意しています。GetListOfModels() は、パラメーターをとらずに携帯電話モデルのリストを返します。一方、getPrice(modelNumber) はパラメーター modelNumber をとり、要求されたモデルの price を返します。これを SOAP 要求の形式で文書化することになりますが、まず最初に SOAP 要求および応答の汎用形式を示すことにしましょう。
リスト 14: SOAP 要求の汎用形式
<SOAP-ENV:Envelope xmlns:SOAP-ENV ="SOAP schema's URI" <SOAP-ENV:Body> <Instance:"Method Name" xmlns:Instance= "URI where method is located"> <parameter1>value</parameter1> <parametern>value</parametern> </Instance:"Method Name"> </SOAP_Envelop:Body> </SOAP-ENV:Envelope> |
1つの SOAP 要求または応答で指定できるサービスのメソッドは、1つだけです。SOAP 要求が含まれているエンベロープの汎用形式は、リスト 14 で示された形式となります。この汎用形式を、リスト 16 の getListOfModels() メソッド呼び出し要求と比較してください。リスト 16 では、メソッドの名前と URI が提供されています。getListOfModels() にパラメーターは必要ないので、<m:getListOfModels> は リスト 16 に示すように空の要素です。
リスト 15: SOAP 応答の汎用形式
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Body> <Instance:"Method Name"+"Response" xmlns:Instance="URI where method is located"> <return> <responseparameter1>value</responseparameter1> <responseparametern>value</responseparametern> </return> </Instance: "Method Name"+"Response"> </SOAP-ENV:Body> </SOAP-ENV:Envelope> |
リスト 15 は汎用 SOAP 応答です。Apache SOAP サーバーは、"Response" キーワードをメソッド名の終わりに追加し、直接の子要素として <return> 要素で戻り値を囲みます。戻り値が複雑な構造である場合は、<return> 要素に、1つ以上の <item> 要素が含まれます。リスト 15 を リスト 17 と比較してみてください。リスト 17 は getListOfModels() メソッドからの実際の応答です。リスト 17 には、項目のリストが Vector データ型として含まれています (これは戻りパラメーターです)。同様にリスト 18 と リスト 19 は、MobilePhoneservice の getPrice() メソッドに対する SOAP 要求と応答を表しています。
リスト 16: getListOfModels() メソッドを呼び出す SOAP 要求
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Body> <m:getListOfModels xmlns:m = "www.mobilphoneservice.com" > </m:getListOfModels> </SOAP-ENV:Body> </SOAP-ENV:Envelope> |
リスト 17: リスト 16 の要求に対する SOAP 応答
<?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance" xmlns:xsd="http://www.w3.org/1999/XMLSchema"> <SOAP-ENV:Body> <ns1:getListOfModelsResponse xmlns:ns1="urn:MobilePhoneservice" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <return xmlns:ns2="http://xml.apache.org/xml-soap" xsi:type="ns2:Vector"> <item xsi:type="xsd:string">M1</item> <item xsi:type="xsd:string">M2</item> <item xsi:type="xsd:string">M3</item> <item xsi:type="xsd:string">M4</item> <item xsi:type="xsd:string">M5</item> </return> </ns1:getListOfModelsResponse> </SOAP-ENV:Body> </SOAP-ENV:Envelope> |
リスト 18: getPrice メソッドに対する SOAP 要求
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance" xmlns:xsd="http://www.w3.org/1999/XMLSchema"> <SOAP-ENV:Body> <m:getPrice xmlns:m ="www.mobilphoneservice.com"> <modelNumber xsi:type ="xsd:String">M1</modelNumber> </m:getPrice> </SOAP-ENV:Body> </SOAP-ENV:Envelope> |
リスト 19: リスト 18 の要求に対する SOAP 応答
<?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance" xmlns:xsd="http://www.w3.org/1999/XMLSchema"> <SOAP-ENV:Body> <ns1:getPriceResponse xmlns:ns1="urn:MobilePhoneservice" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <return xsi:type="xsd:string"> 5000 </return> </ns1:getPriceResponse> </SOAP-ENV:Body> </SOAP-ENV:Envelope> |
このセクションでは、第 1 回で紹介した WSDL サービスを Apache SOAP サーバーに配置します。Apache SOAP ツールキットは、WSDL サービス情報を配置ディスクリプター・ファイルに保管します。この配置ディスクリプターには、WSDL サービスの名前と、そのサービスに含まれているすべてのメソッドが含まれます。配置ディスクリプターは、実行時に SOAP サーバーにこれらのサービスの名前を提供します。同じ配置ディスクリプター・ファイルに、インターフェースを実装する JavaBean コンポーネントのアドレスも含まれます。
リスト 20: スケルトン配置ディスクリプター
<isd:service xmlns:isd="http://xml.apache.org/xml-soap/deployment" id="URN:SERVICE-URN"> <isd:provider type="java" scope="Request" methods="EXPOSED-METHODS"> <isd:java class="IMPLEMENTING-CLASS"/> </isd:provider> <isd:faultListener>org.apache.soap.server.DOMFaultListener </isd:faultListener> </isd:service> |
リスト 20 は、WSDL ベースのサービス配置ディスクリプターとして使用するために、3 ビットの情報 (URN:SERVICE-URN、EXPOSED-METHODS、および IMPLEMENTING-CLASS) が必要な、スケルトン配置ディスクリプターです。URN:SERVICE-URN は、配置されるサービスの名前です。この場合は、"urn:MobilePhoneservice" になります。EXPOSED-METHODS は、このサービスで提供されるメソッドの、シングル・スペースで区切ったリストです。この配置では、getListOfModels getPrice になります。
IMPLEMENTING-CLASS は、たとえば samples.phonequote.MobilePhoneservice のような、完全なパスを持つ Java クラスの名前です。この場合、このアプリケーションのテスト中に以下のようなディレクトリー構造がありました。
Apache SOAP サーバー: C:\foo\SOAP-2_2
携帯電話サービスの実装:
C:\foo\SOAP-2_2\samples\phonequote\MobilePhoneservice
IMPLEMENTING-CLASS パスは、SOAP ツールキットのインストール先ディレクトリーを示します。Java クラスの実際の実装は指定していません。実装はビジネス・ロジックに依存するもので、内容はさまざまだからです。
リスト 21: MobilePhoneservice の配置ディスクリプター
<isd:service xmlns:isd="http://xml.apache.org/xml-soap/deployment" id="urn:MobilePhoneservice"> <isd:provider type="java" scope="Request" methods="getListOfModels getPrice"> <isd:java class="samples.phonequote.MobilePhoneservice"/> </isd:provider> <isd:faultListener> org.apache.soap.server.DOMFaultListener </isd:faultListener> </isd:service> |
リスト 21 は、第 1 回で紹介した WSDL ファイル用の、完全な配置ディスクリプターです。
サンプル・アプリケーションを使って、SOAP クライアントの SOAP サーバーとの通信をデモンストレーションしましょう。そのための 3つのリスト、Startup.html (リスト 22)、Operation.html (リスト 23)、および Execute.jsp (リスト 24) を用意しました。
StartUp.html (リスト 22) は、ユーザーに GUI を提供し、どの SOAP メソッドを呼び出したいかを尋ねる、単純な HTML ファイルです。ユーザーはメソッドを選択します。
リスト 22: フロントエンドとして動作する単純な HTML ページ
<HTML> <BODY bgcolor="Teal"> <br/> <p align="center"> <font size="5" face="Arial" color="white"><b> SOAP method invocation demo </b></font> </p> <hr/> <font face="Arial" color="whitesmoke" size="3"> <br/><b> Click any of the method name to execute.<br/> 1. Get the List of all Models that we manufacture.... <a href="execute.jsp?index=1"> <font color="orange"> GetListOfModels </font></a> <br/> 2. Get the Price of any particular model...................... <a href="operation.html"> <font color="orange"> GetPrice </font></a> </b> </BODY> </HTML> |
Operation.html (リスト 23) では、メソッド起動呼び出しに使うパラメーターを指定するようにユーザーに求めます。
リスト 23: ユーザーの選んだメソッドに応じて、GUI を提供する
<HTML> <BODY bgcolor="Teal"> <br/> <p align="center"> <font size="5" face="Arial" color="white"><b> GetPrice Operation input Form </b> </font></p> <hr/> <p align="center"> <form action="execute.jsp" method="POST"> <input type="hidden" name="index" value="0"> <table textColor="white"> <tr><td> <font color="whitesmoke"><b>Description :</b></font> </td><td><font color="whitesmoke"> Method GetPrice is used to Get Price of given Model Number</font> </td></tr> <tr><td> <font color="whitesmoke"><b>Parameter(s)</b></font></td><td> </td></tr> <tr><td><font color="whitesmoke">Model Number </td></font> <td><font color="whitesmoke"> <input type="text" name="parameter" size="30"> (required) </font> </td></tr> <tr><td> </td><td><input type="Submit" value="Invoke"> </td></tr> </font> </table> </form> </p> </BODY> </HTML> |
Execute.jsp (リスト 24) には、注目すべきコードがすべて含まれています。ここでは、どのメソッドが呼び出されたか、およびどのパラメーターが渡されたかを検出します。それからメソッド起動呼び出しをリモート・サーバーに送信します。
リスト 24: メソッドを検出し、起動呼び出しをリモート・サーバーに送信する
<%@ page language="java" import="java.util.Vector" %>
<%@ page import="java.net.MalformedURLException, java.net.URL" %>
<%@ page import="java.util.Vector" %>
<%@ page import="org.apache.soap.SOAPException,
org.apache.soap.Constants" %>
<%@ page import="org.apache.soap.rpc.Call, org.apache.soap.rpc.Response,
org.apache.soap.rpc.Parameter" %>
<%@ page import="org.apache.soap.transport.http.SOAPHTTPConnection" %>
<%@ page import="org.apache.soap.Fault" %>
<HTML>
<BODY bgcolor="Teal">
<br/>
<p align="center">
<font color="whitesmoke">
<%
boolean isParameter = false ;
SOAPHTTPConnection soapTransport = new SOAPHTTPConnection();
// Address of the remote server.
// Normally this should be dynamically passed and detected.
// We have hard coded it only for demonstration.
URL url = new URL ("http://localhost:8080/soap/servlet/rpcrouter");
// Build the call.
Call call = new Call ();
call.setTargetObjectURI ("urn:MobilePhoneservice");
call.setSOAPTransport (soapTransport);
call.setEncodingStyleURI(Constants.NS_URI_SOAP_ENC);
// We'll detect which method user selected
// and give a call accordingly.
// We'll pass parameters if present.
if (request.getParameter("parameter")!=null)
isParameter = true;
if (request.getParameter("index").equals("0"))
{
call.setMethodName("getPrice");
Vector params = new Vector();
String message = new String (request.getParameter("parameter"));
params.addElement (new Parameter("message", String.class,
message , null));
call.setParams(params);
}
else
call.setMethodName("getListOfModels");
Response resp = call.invoke ( url, /* actionURI */ " );
out.println("<p align=left>
<font size=\"4\" face=\"Arial\" color=\"white\">
Response of [ "+call.getMethodName()+" ]
</font><hr/>");
// Check the response.
if (resp.generatedFault ()) {
Fault fault = resp.getFault ();
out.println("<b>Fault is:</b>"+ fault.getFaultCode ()
+" ["+fault.getFaultString ()+"]");
} else {
Parameter result = resp.getReturnValue ();
out.println("<b>Response is: </b>"+ result.getValue ()+");
}
%>
<font>
</p>
</BODY>
</HTML>
|
このアプリケーションを実行するためには、2つの Apache SOAP サーバーが必要になります。一方のサーバーは、ユーザーおよびホストのリスト 22、リスト 23、およびリスト 24 に質問をします。他方のサーバー (リモート・サーバーとも呼ばれます) は、第 1 回で紹介した WSDL ベースのサービスを配置する必要がある場所です (前のセクション、「SOAP サーバーへの WSDL ベースのサービスの配置」で説明しました)。Execute.jsp (リスト 24) では、デモンストレーションのみの目的で、リモート・サーバーのアドレス http://localhost:8080/soap/servlet/rpcrouter をハードコーディングしました。実際に使用する場合は WSDL ファイルからこのアドレスを読み取ります。
このセクションは、単純データ型と複合データ型の区別の説明から始めましょう。その後、これらのデータ型を SOAP でエンコードする方法を示します。
単純型には、string、float、integer、enumeration などがあります。たとえば、携帯電話の "名前" は、"string" の型を持ちます。複合型は、単純型から形成されますが、単一のエンティティーを表します。たとえば、"Student" 型レコードは、"string" 型の "studentName" や、"int" 型の "studentRollNumber" などの異なる属性を持ちますが、単一のエンティティー、"Student" を表しています。
リスト 25 には、"Mobile" という名前の複合データ型が含まれています。この型を、後に SOAP 要求で使用することになります。
リスト 25: "Mobile" 型の構造を定義するスキーマ
1<? xml version="1.0" ?> 2<xsd:schema xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance" 3 xmlns:xsd="http://www.w3.org/1999/XMLSchema"> 4 targetNameSpace= "www.mobilephoneservice.com/phonequote"> 5 <xsd:element name ="Mobile"> 6 <xsd:complexType> 7 <xsd:element name="modelNumber" type="xsd:int"> 8 <xsd:element name="modelName" type="xsd:string"> 9 <xsd:element name="modelWeight" type="xsd:int"> 10 <xsd:element name="modelSize" type="xsd:int"> 11 <xsd:element name="modelColor"> 12 <simpleType base="xsd:string"> 13 <enumeration value="white" /> 14 <enumeration value="blue" /> 15 <enumeration value="black" /> 16 <enumeration value="red" /> 17 <enumeration value="pink" /> 18 </simpleType> 19 </xsd:element> 20 </complexType> 21 </xsd:element> 22</xsd:schema> |
リスト 25 の行 5 は、私たちが使用する型の名前 (Mobile) を示しており、行 6 は、それが複合データ型であることを確認しています。複合データ型には属性があります。行 7 から行 12 は、副要素として定義された、"Mobile" データ型の属性を示しています。
行 7 で宣言された要素は、"Mobile" 型に、"modelNumber" という名前の属性があること、および その型が "int" である (つまり、"modelNumber" は整数値だけしかとれない) ことを示しています。同様に、行 9 と行 10 で宣言された要素は、同じ型を持っていますが、属性名は異なります。行 8 で定義された要素は、"string" 型の属性名 "modelName" を持っています。
行 11 の要素は、行 12 に "simpleType" という名前の副要素があるので理解するにはもう少し知識が必要です。ここでは、複合型 Mobile の内部に単純型を定義します。simpleType の名前は、"modelColor" であり、これは "enumeration" です。これには属性 "base" があり、値 "xsd:string" を持っています。この値は、単純型 "modelColor" に、SOAP スキーマで定義された、"string" 型の機能があることを表します。行 13 から行 17 の各 <enumeration> タグは、属性 "value" ("white"、"blue"、"black"、"red"、および "pink") を持ちます。このように列挙される型では、複数のオプションから 1つの値を選択できます。
リスト 26 は、SOAP 要求での複合型の使用を表しています。このリストは、Body 要素で要求を指定するエンベロープを示しています。そこで "m" ネーム・スペースの addModel メソッドを呼び出します。リスト 26 では、リスト 25 で定義したデータ型 "Mobile" を使います。
AddModel メソッドは、"Mobile" 型の引数をとります。"msd" ネーム・スペース参照で、"Mobile" 構造を参照することになります。リスト 26 の、<SOAP-ENV:Envelope> 要素での "xmlns:msd" 宣言を参照してください。これは、SOAP 要求でユーザー定義のデータ型を配置する例です。
リスト 26: リスト 25 で定義した "Mobile" 構造の実装
1 <SoAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 2 xmlns:xsd="http://www.w3.org/1999/XMLSchema" 3 xmlns:msd="www.mobilephoneservice.com/phonequote"> 4 <SOAP-ENV:Body> 5 <m:addModel xmlns:m="www.mobilephoneservice.com"> 6 <msd:Mobile> 7 <modelNumber>1</modelNumber> 8 <modelName>mlr97</modelName> 9 <modelWeight>10</modelWeight> 10 <modelSize>4</modelSize> 11 <modelColor>white</modelColor> 12 </msd:Mobile> 13 </m:addModel> 14 </SOAP-ENV:Body> 15<SOAP-ENV:Envelope> |
この第 2 回では、SOAP の構文、要求、応答、HTTP バインディング、および e-mail での SOAP の使用について学習しました。また、Apache SOAP クライアントとしてサービスを提供する Apache SOAP サーバーについても触れました。最後にユーザー定義のデータ型のトピックについて簡単に説明をしましたが、このトピックは詳細にわたる学習が必要な高度なトピックでした。シリーズ 第 3 回では、ユーザー定義のデータ型についてさらに多くの例を示す予定です。また、SOAP の相互運用性 (つまり、異なるベンダーからの SOAP 実装がどのように相互に調整されるか) についても考察するつもりです。
- Simple Object Access Protocol (SOAP) 1.1 は、W3C での SOAP の公式仕様です。
- この記事シリーズの第 1 回 :WSDL による Web サービスの配置
- XML.Com の SOAP 関連の記事はお勧めです。
- introduction to SOAP basics。
- 『Understanding SOAP』 (Kenn Scribner 他著 Sams Publishing)
- 『Professional Java SOAP』 (Henry Bequet 著 Wrox Press Inc)