たのしいXML: SOAP入門

2007年07月08日(日)更新


■SOAPを学びましょう

ここでは、SOAP Version 1.2の基本的なことを理解し、Axisを使って実際にSOAPメッセージのやりとりをできたらいいなと思います。

SOAP Version 1.2は、2003年7月24日にW3Cの勧告(Recommendation)として公開されました。最初は、この中の"Part 0: Primer"を見ながらstudyしてみたいと思います。

解説担当の「さら」です

なお、本格的な翻訳ではありませんので、その点はご容赦ください。


■SOAP Version 1.2

-- 目次 --

1. はじめに
1.1 概要
1.2 表記について
2. 基本的な利用シナリオ
2.1 SOAPメッセージ
2.2 SOAPメッセージ交換
2.2.1 会話的なメッセージ交換
2.2.2 リモート・プロシジャ・コール
2.3 Faultシナリオ
3 SOAP処理モデル
3.1 role属性
3.2 mustUnderstand属性
3.3 relay属性
4. 色々なプロトコルバインディングの使用
4.1 SOAP HTTPバインディング
4.1.1 SOAP HTTP GETの使用
4.1.2 SOAP HTTP POSTの使用
4.1.3 Webアーキテクチャに適合したSOAPの使用
4.2 EMailでSOAP
5. 発展的利用シナリオ
5.2 SOAP中継者を使う
5.2 他のエンコーディングスキーマを使う
6. SOAP 1.1 と SOAP 1.2 の違い
7. 参照資料
A. 謝辞


1. はじめに

SOAP Version 1.2 Part 0: Primer はSOAP Version 1.2 の仕様に記載されている機能を簡単に理解できるようにしたチュートリアルです。ここではSOAPメッセージの構造とSOAPメッセージがやりとりされるパターンを説明し、SOAPがどんな風に使われるかを理解できるようになっています。

特に、色々な利用シナリオを紹介しSOAPの特徴的な機能を説明します。また、SOAP Version 1.2 Part 1: Messaging Framework と SOAP Version 1.2 Part 2: Adjuncts に記述された標準について補足します。

これを読んで理解するためには、次のことについてある程度知っていると良いです。

  • XMLの基本的な文法
  • URIやHTTPといったWebに関する概念

ここでは、アプリケーション設計者などのSOAPの利用者向けにSOAP Version 1.2の重要な特徴的な機能に焦点をあてて説明しますので、細かいところは省略されています。主な仕様についての参照先は都度示されますので、それを参照してください。

[SOAP Part1] は、SOAP envelopeを定義しています。SOAP envelopeというのは、SOAPメッセージの内容を構成するものを含む、SOAPメッセージ全体そのものです。SOAPメッセージには、たとえば、その内容の全部(または一部)をだれが取り扱うべきなのか、とか、その部分の処理は必須なのかオプショナルなのかといった情報が含まれます。
また、[SOAP Part1]は、protocol binding frameworkも定義しています。protocol binding frameworkは、SOAPメッセージをやりとりするための通信用プロトコルの実装に応じた仕様(protocol binding)がどのように記述されるのかを示します。

[SOAP Part2] はSOAPのデータモデルを定義しています。[SOAP Part1]で規定されているprotocol binding framework の実装やRPC(Remote Procedure Calls)で使われるデータ型に特定のエンコーディングが使われます。このbindingでは、HTTPのPOSTリクエスト/レスポンスやHTTPのGETに対するレスポンスにSOAPメッセージのやりとりも可能となっています。

1.1 概要

SOAP Version 1.2 は、ネットワーク分散環境でシステム同士が構造化・型付けされた情報を交換するための、XMLベースの情報の定義をします。[SOAP Part1]では、SOAPメッセージは[XML Infoset]で規定された内容表現方法に基づいているものと説明しています。Infoset(XML情報集合:XMLデータに含まれる情報の種類を抽象的に定義したものです)は異なった通信路上での文書(データ)表現を持つことができますが、その代表的(共通的)な例は[XML 1.0]に基づく文書(データ)です。

SOAPは基本的にステートレスで、一方通行のメッセージ伝達に関する規約なのですが、アプリケーションとしては、下位のプロトコルやアプリケーション固有の情報を利用して、もっと複雑な双方向のやりとりのケース(たとえば、リクエスト/レスポンス、リクエスト/複数レスポンスなど)をすることができます。SOAPは、ルーティング、データトランスファー、ファイヤウォールの通過などによって伝送されるアプリケーション固有のデータの意味については関知しませんが、SOAPはアプリケーション固有の情報が伝達されるためのフレームワークを提供します。またSOAPは、SOAPメッセージを受取ったときに要求されるアクションについて記述しています。

本書の2章ではSOAPの基本的な事柄について、最も簡単な使用例(一方通行のSOAPメッセージ)に始まって、RPCを含んだ色々なリクエスト/レスポンス型の交換の例を説明します。

3章ではSOAPの処理モデルの概要について、メッセージの生成ルール、メッセージを受取ったときのメッセージの処理ルール、伝送の中継者がメッセージのどの部分を挿入・削除・変更できるのかのルールを説明します。

4章では、色々なシナリオを実現するためにSOAPメッセージが伝送される方法について説明します。[SOAP Part2]で規定されているSOAP HTTP bindingと電子メールを使ってどのように伝送されるかの例を含んでいます。HTTP bindingの一部として、HTTP POSTメソッドとHTTP GETによる二つのメッセージ交換パターンを紹介します。それらの例では、安全に情報を取得するRPCが World Wide Web の原則に沿ったやり方で行われるSOAPメッセージ交換にどう使われるのかも説明します。

5章ではもっと複雑な利用シナリオで使われるSOAPの色々な性質の取り扱いについて説明します。そこでは、header要素によって可能な拡張のしくみについての説明も含みます。header要素は、通信しているアプリケーションに付加価値サービスを提供する特定のSOAP中継ノードに対して提供されます。またheader要素は、SOAPメッセージ中のアプリケーション固有データをシリアライズするためのエンコーディングスキーマを使用します。

6章では[SOAP 1.1]からの変更点を説明します。

7章では参照文献を示します。

本書で使われている用語や概念について簡単に参照できるように、それぞれについての詳細仕様へのリンクが設定されています。

1.2 表記について

SOAP envelopeとSOAPメッセージのサンプルは[XML 1.0]文書として例示されます。

[SOAP Part1]では、SOAPメッセージは[XML Infoset]で規定された内容表現方法に基づいているものと説明しています。InfosetはXMLデータに含まれる情報の種類を抽象的に定義したものです。SOAP XML InfosetsとXML文書との違いは、このprimerをSOAP入門として使う人たちにとってはあまり関心がないでしょうね。 この違いを気にする方は、ここでのサンプルを対応するXML infosetsへの参照として理解する必要があります。この点の詳細なことは、本書の4章に記載されています。

ここで使っている名前空間のprefix(接頭辞)は次のようにSOAPの名前空間にそれぞれ関連付けられています。

また、名前空間のprefix "xs"と"xsi"は次のように関連付けられます。両方とも[XML Schema Part1][XML Schema Part2]に定義されている名前空間です。

  • xs: http://www.w3.org/2001/XMLSchema
  • xsi: http://www.w3.org/2001/XMLSchema-instance

(注)他の名前空間のprefixは任意ですし、意味的には重要ではありません。

"http://example.org/..." とか "http://example.com/..."という形式の名前空間URIはアプリケーションに依存または文脈依存のURI[RFC 2396]を表わしています。


ここまでは、どうも硬くなってしまいました。ごめんなさい。

「2 基本的な利用シナリオ」に入る前に、知っておいたほうが良い用語が、SOAP Version 1.2 Part 1: Messaging Framework1.5 SOAP Terminologyに記載されていますのでそれをここに載せておきますね。

解説担当の「さら」です

(1) プロトコル

SOAP
SOAPメッセージの形式と処理ルールについての公式の規約です。これらの規約は、SOAPメッセージの経路に沿って情報交換する目的でSOAPメッセージを生成したり受取ったりする[SOAPノード]間の相互のやりとりを含んでいます。
SOAPノード
SOAPメッセージを運び・受取り・処理・中継するのに必要な処理ロジックをSOAP勧告仕様の規約に従って実現したもの(ソフトウェア)です。SOAPノードは、SOAPメッセージをきちんと交換するためのルール( 2. SOAP処理モデル を参照)に従って処理する責任があります。SOAPノードは下位のプロトコルが提供する複数のSOAPバインディングを通じてサービスにアクセスします。
SOAPロール
SOAPメッセージを処理する上で、SOAPの受信者に期待される機能です。SOAPの受信者は複数のロールを持つ(役割を演じる)ことができます。
SOAPバインディング
通信プロトコルでSOAPメッセージを運ぶための規約のことです( 4. SOAPプロトコルバインディングフレームワーク 参照)。SOAPバインディングの例には、HTTP本体やTCPストリームに含まれるSOAPメッセージがあります。
SOAPフィーチャ
SOAPメッセージングフレームワークの拡張です( 3. SOAP拡張モデル 参照)。フィーチャの例には、"reliability"、"security"、"correlation"、"routing"、そして"Message Exchange Patterns"があります。
SOAPモジュール
SOAPモジュールは3.3 SOAPモジュールルールに従ったSOAPヘッダの構文と意味を含む仕様です。SOAPモジュールは、ゼロかそれ以上のフィーチャを実現するものです。
SOAP MEP(message exchange pattern)
ひとつ以上のSOAPプロトコルバインディングフレームワークで実現されるSOAPノード間のSOAPメッセージ交換のためのテンプレートです( 4. SOAPプロトコルバインディングフレームワーク 参照)。SOAP MEPはSOAPフィーチャの具体例です( 3.2 SOAP Message Exchange Patterns (MEPs) 参照)。
SOAPアプリケーション
SOAP処理モデルに準拠したSOAPメッセージを生成したり使用したりするソフトウェアです( 2. SOAP処理モデル を参照)。

(2) データカプセル化

SOAPメッセージ
SOAPノード間通信の基本単位です。
SOAPエンベロープ
SOAPメッセージの最も外側の要素です。
SOAPヘッダ
ゼロかそれ以上のSOAPヘッダブロックの集合です。各SOAPヘッダブロックは、SOAPメッセージ経路上のどのSOAP受信者に宛てたものでも良いです。
SOAPヘッダブロック
処理可能なユニットとして論理的に構成されたデータを区切る、SOAPヘッダ内のひとつの要素です。
SOAPボディ
SOAPメッセージ経路上の最終SOAP受信者に宛てた、ゼロかそれ以上の要素の集合です( 5.3 SOAPボディ を参照)。
SOAPフォルト
SOAPノードが生成した、フォルト情報(エラー情報)を含むSOAP要素です。

(3) メッセージの送信者・受信者

SOAPメッセージ
SOAPノード間通信の基本単位です。
SOAP送信者
SOAPメッセージを送信するSOAPノードです。
SOAP受信者
SOAPメッセージを受信するSOAPノードです。
SOAPメッセージ経路
ひとつのSOAPメッセージが通過するSOAPノード群です。この経路には、第一SOAP送信者、ゼロかそれ以上のSOAP中継者、そして最終SOAP受信者が含まれます。
第一SOAP送信者
SOAPメッセージ経路の最初のポイントでSOAPメッセージを生成するSOAP送信者のことです。
SOAP中継者
SOAP中継者は、SOAP受信者でSOAP送信者でもあり、SOAPメッセージに宛先として指定できます。SOAP中継者は、自分(SOAP中継者)に送られたSOAPヘッダブロックを処理し、最終SOAP受信者に向けてSOAPメッセージを転送します。
最終SOAP受信者
最終SOAP受信者はSOAPメッセージの最終的な宛先です。SOAPボディと自分(最終SOAP受信者)に送られたSOAPヘッダブロックを処理する責務があります。ある環境では、たとえばSOAP中継者でのトラブルで、SOAPメッセージが最終SOAP受信者に届かないことがあります。最終SOAP受信者は、(最終SOAP受信者に宛てられた)SOAPメッセージに対するSOAP中継者になることはできません( 2. SOAP処理モデル 参照)。

 


2 基本的な利用シナリオ

SOAPメッセージは基本的にはSOAP送信者からSOAP受信者への一方向の伝送ですが、より複雑なやりとりのパターン(たとえばリクエスト/レスポンスといった簡単なパターンから複数の対話的なメッセージ交換まで)を実現するために、アプリケーションによって複数のSOAPメッセージが組合わせて使われることが想定されています。

この入門書ではまず最初に、「旅行予約アプリケーション」を例に、SOAPメッセージの構造と単純な利用シナリオを見ていただきます。また、このアプリケーションのシナリオを使ってSOAPメッセージの色々な特徴を見ていただきます。このシナリオでは、「旅行予約アプリケーション」が、ある会社員のために旅行予約をする目的で「旅行予約サービス」とやりとりをします。「旅行予約アプリケーション」と「旅行予約サービス」との間の情報交換はSOAPメッセージで行われます。

旅行予約アプリケーション」から送信されたSOAPメッセージの最終SOAP受信者は「旅行予約サービス」ですが、SOAPメッセージになんらかの処理を加える、1つかそれ以上のSOAP中継者を経由しても良いのです。そうしたSOAP中継者の簡単な例としては、旅行リクエスト(SOAPメッセージ)のログを取ったり、監査したり、または訂正したりするようなことが考えられます。サンプルについてや、SOAP中継者の振舞いや役割についてのもっと詳しい説明は、5.1節に譲ります。

2.1節では、SOAPメッセージとして表現される「旅行予約リクエスト」について説明します。また、SOAPメッセージを構成する色々な部分についても説明します。

2.2.1節では、同じシナリオを使って、「旅行予約サービス」からの応答を示すSOAPメッセージを説明します。(応答の)SOAPメッセージは、旅行リクエストの処理のためにやりとりされるメッセージのひとつです。

2.2.2節では、旅行予約の内容を旅行者が了承し、旅行予約と旅行サービスアプリケーション間の交換(RPCとしてモデル化されます)による、予約での支払い確認について説明します。

2.3節では、フォールト処理の例を説明します。

 


2.1 SOAPメッセージ

"Example 1"は、旅行予約データのSOAPメッセージ例です。

Example 1:  ヘッダブロックとボディを含んだ旅行予約のSOAPメッセージの例
<?xml version='1.0' ?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"> 
 <env:Header>
  <m:reservation xmlns:m="http://travelcompany.example.org/reservation" 
          env:role="http://www.w3.org/2003/05/soap-envelope/role/next"
           env:mustUnderstand="true">
   <m:reference>uuid:093a2da1-q345-739r-ba5d-pqff98fe8j7d</m:reference>
   <m:dateAndTime>2001-11-29T13:20:00.000-05:00</m:dateAndTime>
  </m:reservation>
  <n:passenger xmlns:n="http://mycompany.example.com/employees"
          env:role="http://www.w3.org/2003/05/soap-envelope/role/next"
           env:mustUnderstand="true">
   <n:name>Ake Jogvan Oyvind</n:name>
  </n:passenger>
 </env:Header>
 <env:Body>
  <p:itinerary
    xmlns:p="http://travelcompany.example.org/reservation/travel">
   <p:departure>
     <p:departing>New York</p:departing>
     <p:arriving>Los Angeles</p:arriving>
     <p:departureDate>2001-12-14</p:departureDate>
     <p:departureTime>late afternoon</p:departureTime>
     <p:seatPreference>aisle</p:seatPreference>
   </p:departure>
   <p:return>
     <p:departing>Los Angeles</p:departing>
     <p:arriving>New York</p:arriving>
     <p:departureDate>2001-12-20</p:departureDate>
     <p:departureTime>mid-morning</p:departureTime>
     <p:seatPreference/>
   </p:return>
  </p:itinerary>
  <q:lodging
   xmlns:q="http://travelcompany.example.org/reservation/hotels">
   <q:preference>none</q:preference>
  </q:lodging>
 </env:Body>
</env:Envelope>

Example 1 のSOAPメッセージは、全体のenv:Envelope要素の中に2つの子要素、env:Headerenv:Bodyを含んでいます。これらの要素の内容はアプリケーションによって規定され、SOAP仕様の一部ではありません。ただ、SOAP仕様ではそれらの要素がどのように処理されなければならないかについて、ある程度規定しています。

SOAPヘッダはオプショナルですが、SOAPのある特徴的機能を説明するためにこの例に含まれています。SOAPヘッダを使って、アプリケーション同士がやりとりする情報(ペイロードといいます)には含まれない情報をSOAPメッセージに含めることができます。

【補足】ペイロード(payload)

ペイロード(payload)は、船や航空機などで運ばれる貨物の有効積載量、荷物の正味のことです(燃料や乗務員の重量は含まれません)。ここでは、SOAP送信者から最終SOAP受信者に宛てた、正味のデータのことを意味しています。つまり、SOAPメッセージからSOAPヘッダを除いた、SOAPボディのことを意味しています。

解説担当の「さら」です

そうした制御情報は、たとえば、メッセージの処理に関する指示や文脈情報を含んでいます。これによって、アプリケーション固有のメッセージルールに合うように、SOAPメッセージを拡張することができます。env:Headerの子要素は、ヘッダブロックと呼ばれます。ヘッダブロックは、SOAP送信者から最終SOAP受信者に至るSOAPメッセージ経路上の(ある)SOAPノードに宛てたデータを論理的にひとまとめにするものです(詳しくはあとで説明します)。

SOAPヘッダは、SOAPがさまざまな用途に利用されることを見越して設計されました。多くの用途では、SOAP中継者と呼ばれるSOAP処理ノードがかかわってきます。SOAP中継者は付加価値サービスを提供することができます。あとで説明しますが、ヘッダはSOAPメッセージ経路上のSOAPノードによって監査・挿入・削除・転送されます(でも、SOAP仕様はヘッダの内容がどうだとか、SOAPメッセージがノード間をどのように通っていくかとか、については扱っていませんので注意してくださいね。)

SOAPボディは、env:Envelopeの子要素として必須の要素で、SOAP送信者から最終SOAP受信者に送られる情報を持ちます。

Example 1 のSOAPメッセージの構成は図のようになっています。

Example 1 のSOAPメッセージの構成

Example 1では、ヘッダは二つのヘッダブロックを持っています。それぞれのヘッダブロックは固有のXML名前空間で定義されていて、SOAPメッセージのボディの全体的な処理に関連する情報をを示しています。この旅行予約サービスアプリケーションでは、(実際の)予約情報の参照識別子とタイムスタンプ(予約日時)を持っているreservationヘッダブロックと、旅行者を識別する情報を持っているpassengerヘッダブロックがあります。

reservationヘッダブロックとpassengerヘッダブロックは、メッセージ経路上の次のSOAP中継者によって処理されなければなりません。でも、もしSOAP中継者がいない場合には、最終SOAP受信者によって処理されなければなりません。このことがメッセージ経路上の次のSOAPノードに宛てられているということは、
"http://www.w3.org/2003/05/soap-envelope/role/next"
の値(以降は、単に"next"と表記します)を持っているenv:role属性で示されています。

env:mustUnderstand属性が"true"のときは、ヘッダを処理するノードが仕様通りにヘッダブロックを処理しなければならないことを示しています(処理できないときは、faultを返します)。env:mustUnderstand="true"となっているか、もしくは他の理由でヘッダブロックが処理されるときには、そのヘッダブロックの仕様にしたがって処理しなくてはならないことに注意してください。そのヘッダブロックの仕様はアプリケーションで定義されるもので、SOAP仕様にはありません。これらの属性に基づくSOAPメッセージの処理については3章で詳しく説明します。

ヘッダブロックにどんなデータが含められSOAPボディがどう扱われるかということは、アプリケーションの設計段階で決められます。覚えておきたいポイントは、ヘッダブロックは、送信者から最終受信者までのメッセージ経路上の色々なノードに宛てて設定することができる、ということです。SOAP中継者は、そのようなヘッダ中のデータに基づいて付加価値サービスを提供することができます。Example 1では、SOAP中継者が何らかの付加的な処理をするためのデータ例として、ヘッダブロックにpassengerデータが含まれています。たとえば、5.1節で後述しますが、このpassengerに対して適切な旅行ポリシーを別のヘッダブロックに持つことで、SOAP中継者によって次のノードに渡されるSOAPメッセージが変更されます。

env:Body要素とその子要素のitinerarylodgingは、最初のSOAP送信者から最終SOAP受信者(旅行サービスアプリケーション)に送られる情報です。ですから、env:Body要素とその内容は、最終SOAP受信者が受取って解釈されることが想定されています。そのSOAPノードが処理する方法についてはSOAP仕様には定義されていなくて、アプリケーションの意味や関連するメッセージフローといった全体的な役割から決定されるものです。

SOAP中継者が最終SOAP受信者の役割を演じてenv:Body要素を処理するかもしれない、ということにご注意ください。このようなことが防止できないとしても、メッセージ送信者が意図したこととは違ったことをして、好ましくない副作用(メッセージ経路上のさらに先のSOAP中継者に宛てたヘッダブロックが処理されないとか)をもたらしてしまうかも知れないようなことは軽々しくされるべきものではありません。

Example 1で示されたようなSOAPメッセージは、異なった下位のプロトコルによって搬送され、色々なメッセージ交換のパターンで使用されても良いです。たとえば、旅行サービスアプリケーションにWebベースでアクセスするときには、HTTP POSTリクエストのボディに含まれるでしょう。別のプロトコルとして、電子メールのメッセージ(4.2節参照)で送信されるかもしれません。4章では、SOAPメッセージが色々な下位のプロトコルで、どのように運ばれるのかを説明します。とりあえず(ここでは)メッセージ搬送のしくみがあるものとしておいて、この章ではSOAPメッセージとその処理について説明することにします。

 


2.2 SOAPメッセージ交換

SOAP Version 1.2は、第一SOAP送信者と最終SOAP受信者との間でXML infosetの形式で指定された情報を運ぶための、シンプルなメッセージフレームワークです。もっと興味深いシナリオだと、これらの二つのノード間で複数のメッセージ交換が行われます。最も簡単なメッセージ交換の例は、リクエスト・レスポンスのパターンです。初期の[SOAP 1.1]の利用では、RPC(Remote Procedure Call)を実現する手段として、このパターンの利用が強調されました。ただし、すべてのSOAPリクエスト・レスポンスをRPCのモデルとして使われるわけではない、ということに注意しておきましょう。でも、リモートコールとそのリターンの記述があらかじめ決められていて、それに従ったメッセージの交換が必要とされる処理をするような場合には、SOAPリクエスト・レスポンスがモデルとして使われます。

リクエスト・レスポンスのパターンでカバーできないような、ずっと大規模な利用シナリオでは、XMLをベースにした内容(contents)がSOAPメッセージに包まれて、行ったり来たりと「会話的」に交換されるモデルが使われるでしょう。その場合の各メッセージの意味は、メッセージを送受信するアプリケーションが知っていることになります。2.2.1節では、旅行予約アプリケーションと旅行サービスアプリケーションが会話的なパターンでXMLベースの内容をSOAPメッセージに包んでやりとりするケースを説明します。また、2.2.2節では、RPCとしてのメッセージ交換モデルの例を説明します。

2.2.1 会話的なメッセージ交換

旅行予約のシナリオの続きとして、"Example 2"は、"Example 1"の旅行予約のリクエストメッセージに対する応答として、旅行サービスから返されたメッセージを示しています。このレスポンスは、リクエストに含まれるいくつかの情報について、すなわち出発地の空港の選択などについて、明確にするように尋ねています。

Example 2:  "Example 1"のリクエストメッセージに対する応答メッセージの例
<?xml version='1.0' ?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"> 
 <env:Header>
  <m:reservation xmlns:m="http://travelcompany.example.org/reservation" 
      env:role="http://www.w3.org/2003/05/soap-envelope/role/next"
           env:mustUnderstand="true">
   <m:reference>uuid:093a2da1-q345-739r-ba5d-pqff98fe8j7d</m:reference>
   <m:dateAndTime>2001-11-29T13:35:00.000-05:00</m:dateAndTime>
  </m:reservation>
  <n:passenger xmlns:n="http://mycompany.example.com/employees"
      env:role="http://www.w3.org/2003/05/soap-envelope/role/next"
           env:mustUnderstand="true">
   <n:name>ナke Jgvan リyvind</n:name>
  </n:passenger>
 </env:Header>
 <env:Body>
  <p:itineraryClarification 
    xmlns:p="http://travelcompany.example.org/reservation/travel">
   <p:departure>
     <p:departing>
       <p:airportChoices>
          JFK LGA EWR 
       </p:airportChoices>
     </p:departing>
   </p:departure>
   <p:return>
     <p:arriving>
       <p:airportChoices>
         JFK LGA EWR 
       </p:airportChoices>
     </p:arriving>
   </p:return>  
  </p:itineraryClarification>
 </env:Body>
</env:Envelope>

前述したように、env:Bodyはメッセージの重要な内容を含んでいます。この例では、XML名前空間"http://travelcompany.example.org/reservation/travel"のスキーマ定義に従った、空港を選択するためのリストを含んでいます。この例では、"Example 1"からのヘッダブロックが返されています(ある子要素の値が変更されていますけど)。こうすることで、SOAPレベルでメッセージを関連させることができるかもしれませんが、そのようなヘッダはアプリケーション固有の利用に使えそうに思われます。

Example 1とExample 2のメッセージ交換は、あるアプリケーションで定義されたスキーマに準拠したXMLベースの内容(contents)がSOAPメッセージによって交換されるケースです。メッセージが運ばれるそうした手段については、4章でもう一度説明します。

そうしたメッセージ交換がどうやって複数の"会話的な"やりとりのパターンを実現するのか、を見るのは易しいことです。Example 3は、Example 2への応答メッセージとして、旅行予約アプリケーションから送られたSAOPメッセージを示しています。そのメッセージでは、Example 2の利用可能な空港のリストからひとつが選択されています。この会話では、各メッセージのヘッダブロック"reservation"の子要素の"reference"要素に同じ値(uuid:093a2da1-q345-739r-ba5d-pqff98fe8j7d)があるので、アプリケーション同士でメッセージ交換ができるようになっています。

Example 3:  旅行予約アプリケーションから送られたExample 2への応答メッセージの例
<?xml version='1.0' ?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"> 
 <env:Header>
  <m:reservation 
     xmlns:m="http://travelcompany.example.org/reservation" 
      env:role="http://www.w3.org/2003/05/soap-envelope/role/next"
           env:mustUnderstand="true">
    <m:reference>uuid:093a2da1-q345-739r-ba5d-pqff98fe8j7d</m:reference>
    <m:dateAndTime>2001-11-29T13:36:50.000-05:00</m:dateAndTime>
  </m:reservation>
  <n:passenger xmlns:n="http://mycompany.example.com/employees"
      env:role="http://www.w3.org/2003/05/soap-envelope/role/next"
           env:mustUnderstand="true">
   <n:name>ナke Jgvan リyvind</n:name>
  </n:passenger>
 </env:Header>
 <env:Body>
  <p:itinerary 
   xmlns:p="http://travelcompany.example.org/reservation/travel">
   <p:departure>
     <p:departing>LGA</p:departing>
   </p:departure>
   <p:return>
     <p:arriving>EWR</p:arriving>
   </p:return>
  </p:itinerary>
 </env:Body>
</env:Envelope>

2.2.2 リモート・プロシジャ・コール

SOAP Version 1.2の設計上のゴールのひとつは、XMLの拡張性と柔軟性を利用して、リモート・プロシジャ・コール(以降、RPCと書くことがあります)をカプセル化することです。SOAP Part 2 section 4では、RPCの呼び出しと応答をSOAPメッセージで運ぶための一定の表現形式が定義されています。ここでは、旅行予約シナリオについて話しを続け、リモート・プロシジャ・コールとその戻りのためのSOAPメッセージの使い方について説明します。

次の例では、クレジットカードを使った旅費支払いを示します。(2.2.1節で説明した会話的なメッセージ交換がされて、旅行日程が確認されていると想定します。)ここではさらに、旅行と宿泊(例には載ってませんが、同様に予約されたと想定)の両方が確認されたときにクレジットカードによる支払請求がされるという、全体の取引処理のなかで支払が発生すると想定されます。旅行予約アプリケーションはクレジットカード情報を提供し、カードに正しく請求されて、ちゃんと予約コードを取得できるように処理します。この、旅行予約アプリケーションと旅行サービスアプリケーションとの間の「予約-請求」処理は、SOAP RPCとしてモデル化されます。

SOAP RPCを呼び出すのには次の情報が必要です。

  1. (メッセージ送付先の)SOAPノードのアドレス
  2. プロシジャ名(またはモジュール名)
  3. プロシジャ(またはモジュール)に渡される入力引数の名前と値。また、出力パラメタや戻り値の名前。
  4. RPCのターゲットであるWeb上のリソースを識別するために使われる引数を、RPCで処理されるデータや制御情報の引数と明確に区別する情報
  5. RPCを行うためのメッセージ交換のパターンと、いわゆる"Web-Method"(後述)の識別子
  6. オプション: SOAPヘッダブロックの一部として運ばれるかもしれないデータ

上記の情報は、IDL(Interface Definition Languages)などのいろいろな方法で表現されます。SOAPはどのIDLも提供しないことにご注意ください。また、上記の情報は、SOAP RPC以外のものを呼び出すのに必要な情報とは微妙に違うということにもご注意ください。

上記項目1.は、SOAPの観点からするとRPCをサポートしているSOAPノード、最終SOAP受信者のことです。最終SOAP受信者は、そのURIを見て指定されたプロシジャ(モジュール)を識別できます。ターゲットURIを有効にする方法は、下位のプロトコルバインディングに依存します。ターゲットを識別するURIは、SOAPヘッダブロックに含まれるかもしれません。[SOAP Part2]で定義されているSOAP HTTPバインディングなどのプロトコルバインディングでは、SOAPメッセージの外側でURIを運ぶ仕組みを提供しています。一般に、プロトコルバインディング仕様のひとつとして、バインディングの一部としてどのようにターゲットURIが運ばれるかが記述されなくてはなりません。4.1節では、HTTPにバインドされた標準のSOAPプロトコルバインディングのケースでURIが運ばれる具体的な例を説明します。

上記項目4.と5.は、World Wide Webの原則に即した方法でSOAPを使ってRPCアプリケーションを確実に実現するために必要とされます。4.1.3節で上記項目4.と5.で提供された情報がどのように使われるのかを説明します。

このあと、Example 4で示されたSOAPメッセージでRPCが適切にターゲットに伝達されるものとしてお話を進めます。本節の目的は、SOAPメッセージで伝えられるRPCのリクエストとリターンに関して、記述方法を説明することです。

Example 4:  SOAP RPCリクエスト(必須のヘッダと二つの入力パラメタを含んでいます)
<?xml version='1.0' ?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" >
 <env:Header>
   <t:transaction
           xmlns:t="http://thirdparty.example.org/transaction"
           env:encodingStyle="http://example.com/encoding"
           env:mustUnderstand="true" >5</t:transaction>
 </env:Header>  
 <env:Body>
  <m:chargeReservation
      env:encodingStyle="http://www.w3.org/2003/05/soap-encoding"
         xmlns:m="http://travelcompany.example.org/">
   <m:reservation xmlns:m="http://travelcompany.example.org/reservation">
    <m:code>FT35ZBQ</m:code>
   </m:reservation>
   <o:creditCard xmlns:o="http://mycompany.example.com/financial">
    <n:name xmlns:n="http://mycompany.example.com/employees">
           Ake Jogvan Oyvind
    </n:name>
    <o:number>123456789099999</o:number>
    <o:expiration>2005-02</o:expiration>
   </o:creditCard>
  </m:chargeReservation>
 </env:Body>
</env:Envelope>

RPCそのものは、env:Body要素の子要素として運ばれます。そしてそれは、プロシジャ(またはメソッド)の名前、ここの例ではchargeReservation、を持つstruct(構造体)としてモデル化されています。(ここで言うstructは、[SOAP Part2]SOOAPデータモデルの概念ですが、よく知られているプログラミング言語で使われている、データ構造やレコード型のモデルと同様のものです。)ここでの例のRPCのデザイン(きちんとした説明はしてませんけど)は、ふたつの入力(in)パラメタ、reservation(予約コードで識別される旅行予約)とcreditCard(クレジットカード情報)をとっています。creditCardはさらにstructになっていて、3つの要素、name(契約者名)、number(カード番号)そしてexpiration(有効期限)から構成されています。

この例では、http://www.w3.org/2003/05/soap-encodingの値を持っているenv:encodingStyle属性は、chargeReservationstructの内容が、SOAPエンコーディングルール、つまり[SOAP Part 2の第3章]で定義されたルール、に従ってシリアライズされていることを示しています。でも、SOAPがこの特定のエンコーディングを規定していたとしても、それを使うかどうかは任意で、SOAPメッセージに含まれるアプリケーション固有のデータについて他のエンコーディング体系を使ってもかまわないのです。env:encodingStyle属性は、ヘッダブロックやボディの子要素のエンコーディングを示すためにあるのです。この属性の値をなににするのかは、アプリケーション次第ですし、通信が可能となっている呼出し元と呼出し先との間の処理能力次第です。5.2節では他のエンコーディングを使用した例を示します。

前述の項目6.に書いたように、RPCでは、プロシジャ(またはメソッド)の一部ではなくても分散環境での呼出し処理に必要な追加情報を必要することもあります。(注: そのような追加の情報はRPCに特有なものではなく、分散環境アプリケーション処理に一般的に必要されるものです。)ここでの例では、RPCの結果が正しく戻るまでにすべてがうまく完了されなければならない項目を処理する全体的なトランザクションで、RPCが実現されています。Example 4は、そのような情報を運ぶのに、最終受信者(env:role属性は指定されていないので、暗黙的に指定されていることになります)に向けられたヘッダブロックのトランザクション(t:transaction)が、どのように使われているかを示しています。(値 "5" はアプリケーションによってセットされているトランザクション識別子です。SOAP RPCメッセージの構文についての話には特に関係が無いので、それ以上のアプリケーションが必要とするような細かなことをヘッダに設定することは、ここでは説明しません。)

さて、請求の例でのRPCは、2つの出力(out)パラメタがあることを示すプロシジャ記述がすでにデザインされているとします。ひとつは予約の参照コードで、もうひとつは予約内容の詳細を見ることができるURLです。RPCの応答は、SOAPメッセージのenv:Body要素の中にstructureとして含まれ、プロシジャ名chargeReservation(お約束として"Response"という語が追加されます)があります。応答の2つの出力(out)パラメタは、問合せに含まれる予約を識別するための英数字のcode、そして予約内容が取り出せるviewAtというURIです。

このことを Example 5a 示します。このRPCが実行されたトランザクションを識別するために、再度同じヘッダが設定されています。

Example 5a:  2つの出力(out)パラメタを含む、Example 4に対するRPCレスポンス
<?xml version='1.0' ?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" >
 <env:Header>
     <t:transaction
        xmlns:t="http://thirdparty.example.org/transaction"
          env:encodingStyle="http://example.com/encoding"
           env:mustUnderstand="true">5</t:transaction>
 </env:Header>  
 <env:Body>
     <m:chargeReservationResponse 
         env:encodingStyle="http://www.w3.org/2003/05/soap-encoding"
             xmlns:m="http://travelcompany.example.org/">
       <m:code>FT35ZBQ</m:code>
       <m:viewAt>
         http://travelcompany.example.org/reservations?code=FT35ZBQ
       </m:viewAt>
     </m:chargeReservationResponse>
 </env:Body>
</env:Envelope>

RPCはしばしば特定の出力パラメタを識別できるような記述を持っています。いわゆる、"return value"(戻り値)ですね。SOAP RPCの慣習では、プロシジャ定義の他の出力パラメタからこの"return value"(戻り値)を区別する方法を提供しています。このことを説明するのに、請求の例についてExample 5aのものとほぼ同様のRPC記述をもったものに変更します。つまり、同じ2つの"out"パラメタに加えて、"confirmed"か"pending"のいずれかの値をとる"return value"(戻り値)を持たせます。この記述にあったRPCレスポンスをExample 5bに示します。このExample 5bのSOAPヘッダは、前の例と同様に、RPCが実行されたトランザクションを特定できる情報を持っています。

Example 5b:  "return value"(戻り値)と2つの出力(out)パラメタを含む、Example 4に対するRPCレスポンス
<?xml version='1.0' ?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" >
 <env:Header>
    <t:transaction
       xmlns:t="http://thirdparty.example.org/transaction"
         env:encodingStyle="http://example.com/encoding"
          env:mustUnderstand="true">5</t:transaction>
 </env:Header>  
 <env:Body>
    <m:chargeReservationResponse 
       env:encodingStyle="http://www.w3.org/2003/05/soap-encoding"
           xmlns:rpc="http://www.w3.org/2003/05/soap-rpc"
             xmlns:m="http://travelcompany.example.org/">
       <rpc:result>m:status</rpc:result>
       <m:status>confirmed</m:status>
       <m:code>FT35ZBQ</m:code>
       <m:viewAt>
        http://travelcompany.example.org/reservations?code=FT35ZBQ
       </m:viewAt>
    </m:chargeReservationResponse>
 </env:Body>
</env:Envelope>

Example 5bでは、"return value"(戻り値)は、rpc:result要素で示されます。rpc:result要素の内容は、m:statusという、構造体(struct)に含まれる他の要素のXML Qualified Name(xs:QName型)を持っています。このm:status要素が実際の"confirmed"という戻り値を持っています。この方法を使うと、スキーマに従ったちゃんとした型の戻り値を返すことができます。、Example 5aのケースのように、もしrpc:result要素が無いときには、戻り値が示されていないか、"void型"、ということになります。

【補足】Example 5b: RPCのreturn value

Example 5a: RPCのreturn value

原則的には、RPCにSOAPを使うこととRPC呼出し・戻りを運ぶための特定の手段を決定することとは別のことで、SOAPのリクエスト-レスポンスメッセージ交換パターンをサポートする別のプロトコルバインディングが、その目的によりふさわしいかもしれません。このメッセージ交換パターンをサポートするプロトコルバインディングは、リクエストとレスポンスを関連させることができるかもしれません。もちろん、RPCを使ったアプリケーションの設計者は、その呼び出しと戻りを関係付けるのにSOAPヘッダに、関連のためのIDをおくようにするかもしれません。それによって、RPCが下位の転送手段の影響を受けないようにすることができます。いずれにしてもアプリケーションの設計者は、SOAP RPCを行うために選んだプロトコルの特徴、たとえば呼出し時間や同期性など、をよく知っていなければなりません。

下位のプロトコルとしてHTTPを使う一般的な利用の場合については「SOAP Part 2 の7章」で標準化されていますが、RPCの呼び出しがHTTPリクエストで、RPCレスポンスがHTTPレスポンスにあたります。4.1節で、HTTPバインディングを使ったRPCの例を説明します。ただ、SOAP RPCの多くの例がHTTPプロトコルバインディングを使っているとしても、プロトコルバインディングはそれだけではない、ということは覚えておきましょう。


2.3 Fault(フォールト)シナリオ

SOAPはメッセージの処理中にfault(フォールト:障害)が起こったときの状況を取り扱うモデルを提供します。SOAPは、結果的にfaultになった条件と、faultを起こすようなメッセージを生成したソフトウェアやその他のノードに通知する能力とを区別します。faultを知らせる能力は、使用されるメッセージ伝送手段に依存します。また、SOAPの下位プロトコルへのバインディング仕様のひとつに、faultがどのように通知されるかという仕様があった場合(めったに無いことですけど)、それにも依存します。この節では、メッセージの受信処理をしているときに発生したfaultを伝送手段が通知することができるものと想定して、SOAPのfaultメッセージの構造を中心に説明します。

env:Body要素は、そのようなフォールト情報の格納場所というもうひとつの役割を持っています。SOAPフォールトモデル(SOAP Part 1, section 2.6を参照のこと)では、すべてのSOAP仕様やアプリケーション仕様によるフォールトが単一の識別可能な要素、env:Body要素要素内のenv:Fault要素を使って通知されるものとします。env:Fault要素は2つの必須の子要素、env:Codeenv:Reason、そして(任意の)アプリケーション固有の情報をenv:Detailに持ちます。もうひとつの任意の子要素、env:NodeはURIでfaultを起こしたSOAPノードを示します。env:Nodeが無い場合は、faultを起こしたSOAPノードが最終SOAP受信者だということを暗に示しています。さらにもうひとつの子要素、env:Roleは、faultを起こしたノードによって実行されていた役割を示します。

env:Code要素は、必須のenv:Code要素と任意のenv:Subcode要素とから構成されています。env:Code要素の内容は、SOAP仕様(SOAP Part 1 section 5.4.6を参照のこと)に規定されています。

"Example 6a" は、"Example 4" のリクエストに対するレスポンスメッセージで、RPC処理のエラーを示しています。

Example 6a:  "Example 4"に対するRPCエラーレスポンス
<?xml version='1.0' ?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"
            xmlns:rpc='http://www.w3.org/2003/05/soap-rpc'>
 <env:Body>
   <env:Fault>
     <env:Code>
       <env:Value>env:Sender</env:Value>
       <env:Subcode>
        <env:Value>rpc:BadArguments</env:Value>
       </env:Subcode>
     </env:Code>
     <env:Reason>
      <env:Text xml:lang="en-US">Processing error</env:Text>
      <env:Text xml:lang="cs">Chyba zpracovani</env:Text>
     </env:Reason>
     <env:Detail>
      <e:myFaultDetails 
        xmlns:e="http://travelcompany.example.org/faults">
        <e:message>Name does not match card number</e:message>
        <e:errorcode>999</e:errorcode>
      </e:myFaultDetails>
     </env:Detail>
   </env:Fault>
 </env:Body>
</env:Envelope>

env:Code要素は、必須のenv:Code要素と任意のenv:Subcode要素とから構成されています。env:Code要素の内容は、SOAP仕様(SOAP Part 1 section 5.4.6を参照のこと)に規定されています。

"Example 6a" では、env:Valueは標準のXML修飾名(xs:QName型)を使って、env:Senderフォールトを示しています。env:Senderフォールトは、なんらかの構文エラーかメッセージ中に不適切な情報があることを示しています。(送信者がenv:Senderフォールトを受けた場合、送信者が再度同様のメッセージを送信する前になんらかの訂正処理を行うことが期待されています。)env:Subcode要素は任意で、"Example 6a"のようにその要素が存在したときには、フォールトの原因となった情報を特定します。"Example 6a"では、env:Subcodeは、RPCに関するフォールトSOAP Part 2 section 4.4で規定されているrpc:BadArgumentsがリクエスト処理失敗の原因だということを表しています。

env:Subcode要素の構造は、必須のenv:Valueとアプリケーション個別に提供可能な任意の(optional)子要素からなる階層構造になっています。env:Code要素の階層構造は、複数のレベルのFaultコードを渡すための手段となっています。env:Valueは、SOAP Version 1.2の仕様(SOAP Part 1 section 5.4.6を参照のこと)で規定されているベースFaultで、すべてのSOAPノードはその意味を理解していなければなりません。ネストしている(env:Subcodeの子要素の)env:Valueはアプリケーション個別で、アプリケーションからの視点でベースFaultをさらに詳細に示します。これらの値のいくつかは、SOAP 1.2のRPCコード(SOAP Part 1 section 5.4.6を参照のこと)のように標準化されるでしょうし、SOAPを使った他の標準で規定されるかもしれません。アプリケーション固有のsubcodeの定義に必要なことは、SOAPフォールト(Fault)の主な区分を定義しているSOAPのenv名前空間とは別の名前空間で修飾することです。アプリケーションがそのsubcodeの値について理解していなければいけないとか、すべてのレベルのsubcodeの値をチェックしなければいけないとかについて、SOAPの視点からは特に要求することはありません。

env:Reason要素は、コンピュータ処理用というよりは人が理解するためのものなので、これが必須項目であっても、その値についての標準化の必要はありません。ですから、フォールトの状況が正確に記述されてさえいれば良いのです。その要素は、ひとつかそれ以上のenv:Text子要素を持っていなければなりませんし、アプリケーションに対して複数の言語でFaultの理由を示せるように、それぞれの要素はユニークなxml:lang属性を持っていなければなりません。(アプリケーションは、SOAPヘッダを使った方法を用いて、Faultを示すテキストの言語を取り決めることができます。ただし、その方法についてはSOAP仕様外です。)

"Example 6a"にはenv:Fault要素中にenv:Node要素がありませんが、それはこのフォールトが最終SOAP受信者によって生成されたことを(暗に)示しています。env:Detailの内容は、"Example 6a"に示すように、アプリケーション個別のものです。

SOAPメッセージの処理中に、必須のヘッダ要素が理解できなかったり、その内容が処理できなかったりしてもFaultが生成されます。ヘッダブロック処理中のエラーも、env:Body要素内のenv:Fault要素を使って通知されますが、その際には、気にさわるようなヘッダブロックですよ、という特別のヘッダブロックenv:NotUnderstoodを伴っています。

 

"Example 6b" は、"Example 4" のリクエストに対するレスポンスメッセージで、t:transactionヘッダブロック処理のエラーを示しています。env:Body内にenv:MustUnderstandというフォールトコードがあることに注目してください。また、理解できなかったヘッダを、特別の(空の)env:NotUnderstoodヘッダブロックのqname属性で示しています。

Example 6b:  "Example 4"のヘッダブロック処理エラーを示すSOAPメッセージ
<?xml version='1.0' ?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope>
 <env:Header>
    <env:NotUnderstood qname="t:transaction"
               xmlns:t="http://thirdparty.example.org/transaction"/>
 </env:Header>  
 <env:Body>
  <env:Fault>
   <env:Code>
    <env:Value>env:MustUnderstand</env:Value>
   </env:Code>
   <env:Reason>
      <env:Text xml:lang="en-US">Header not understood</env:Text>
      <env:Text xml:lang="fr">En-t黎e non compris</env:Text>
   </env:Reason>    
  </env:Fault>
 </env:Body>
</env:Envelope>

もし、理解できない必須のヘッダブロックが複数あったときには、例にあるようなenv:MustUnderstoodヘッダブロックが複数並び、各env:MustUnderstoodヘッダブロックのqname属性で識別されます。

 


3 SOAP処理モデル

これまでのところでSOAPメッセージのいくつかの構文についてみながら、基本的なメッセージ交換のパターンをみてきました。本章ではSOAP処理モデル( SOAP Part 1, section 2に規定されています。)の概要を説明します。SOAP処理モデルは、SOPAメッセージを受信したSOAPノードが行う処理を示します。

"Example 7a"は、複数のヘッダブロックのあるSOAPメッセージです(簡潔に示すために各ヘッダブロックの内容は省略してます)。これ以降の本章内で処理モデルのいろいろなことがらについて説明するのにこれらのヘッダブロックを使います。

Example 7a:  いろいろなヘッダブロックを含んだSOAPメッセージ
<?xml version="1.0" ?>
 <env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
   <env:Header>
     <p:oneBlock xmlns:p="http://example.com" 
            env:role="http://example.com/Log">
     ...
     ...
     </p:oneBlock>
     <q:anotherBlock xmlns:q="http://example.com"
       env:role="http://www.w3.org/2003/05/soap-envelope/role/next">
     ...
     ...
     </q:anotherBlock>
     <r:aThirdBlock xmlns:r="http://example.com">
     ...
     ...
     </r:aThirdBlock>
   </env:Header>
   <env:Body >
     ...
     ...
   </env:Body>
 </env:Envelope>

SOAP処理モデルはSOAPメッセージを受信したノードが(論理的に)何をするのかを説明しています。SOAP仕様のメッセージの各部分、つまりはSOAPの"env"名前空間で示される各要素を解析することが、ノードに求められます。それらの要素はenvelopeそのもので、ヘッダ要素とボディ要素です。まず最初のステップは、もちろんですけど、SOAPメッセージが構文上正しいかどうかの全般的なチェックです。つまり、 SOAP Part1, section 5.に規定されているSOAP XML infosetのうちの特定のXML構成要素(処理命令とDTD)の制約にSOAPメッセージが適合しているかどうかです。

【補足】 SOAP Part1, section 5.には、SOAPメッセージのXML infosetには処理命令(Processing Instruction)とDTDを含んではいけない、とあります。XML infoset (XML Information Set)は、いろいろなXML応用仕様から共通的に参照できるように定義したXMLのデータモデルで、用語統一的な意味合いがあります。

解説担当の「さら」です

 


3.1 role属性

最初のステップの後のステップで行われるヘッダブロックとボディの処理は、メッセージを処理するSOAPノードが引き受ける role に依ります。SOAPは、ヘッダブロックに置ける(任意の)env:role属性(値はxs:anyURI)を定義しています。それはヘッダブロックに示した宛先のノードが担う役割を指定します。SOAPノードは、URIの値で示された役割を受け持つ場合、ヘッダブロックを処理することを求められます。SOAPノードがどのように特定の役割を果たすのかということは、SOAP仕様には含まれません。

以下の3つの標準化されたroleが定義されています。( SOAP Part 1, section 2.2 を参照願います。)

  • "http://www.w3.org/2003/05/soap-envelope/role/none" (以降、"none"と表記します)
  • "http://www.w3.org/2003/05/soap-envelope/role/next" (以降、"next"と表記します)
  • "http://www.w3.org/2003/05/soap-envelope/role/ultimateReceiver" (以降、"ultimateReceiver"と表記します)

"Example 7a" のヘッダブロックp:oneBlockは URI http://example.com/Logで定義されたアプリケーション定義のroleを担うSOAPノードに宛てられたものです。説明の都合上、そのヘッダブロックに関する仕様としては、このroleに適合するSOAPノードはメッセージ全体を記録することが求められるものとします。

env:roleの値がnextのヘッダブロックを含むメッセージを受信したすべてのSOAPノードは、その要素の内容を処理できなくてはなりません。これはすべてのSOAPノードが負わなくてはならいな標準のroleなのです。このように属性が付与されたヘッダブロックは、メッセージ経路に沿った次の(next)SOAPノードによって調べられて、(できれば)処理されることが期待されます。また、そのヘッダブロックは、メッセージ経路上の前のノードの処理結果として削除されないものと想定しています。

"Example 7a" のq:anotherBlockヘッダブロックは、メッセージ経路上の次のノードに宛てられています。このケースでは、アプリケーション定義ロール(role) env:role="http://example.com/Log" を担うノードに受信されたSOAPメッセージは、SOAP定義のnextロール(role)も果たされなくてはなりません。このことは、メッセージの最終受信者であるノードについても当てはまります。それは明らかに(かつ暗黙的に)メッセージ経路上の次の(next)ノードなので、nextロール(role)を負うことになります。

"Example 7a" の3つ目のヘッダブロック aThirdBlockにはenv:role属性がありません。これは、ultimateReceiverロールを担うSOAPノードに宛てたものです。ultimateReceiverは明示的に宣言するか、env:role属性がヘッダブロックに無いときには暗黙的に示されますが、これはSOAPメッセージの最終受信者のロールを担うSOAPノードによって引き受けられます。aThirdBlockenv:role属性が無いということは、このヘッダ要素がultimateReceiverロールを担うSOAPノードに宛てられていることを意味しています。

env:Body要素はenv:role属性を持っていないことに注意してください。ボディ要素は常にultimateReceiverロールを担うSOAPノードに宛てられています。その意味では、ボディ要素は最終受信者に宛てたヘッダブロックのようなものです。しかし、SOAPノード(典型的にはSOAP中継者)は、もしそのSOAPノードが最終受信者のロール以外のロール(役割)を担っているときには、それをスキップしても良いという点で明らかに違っています。

SOAPは、子要素がXML名前空間名で修飾されることを勧告している以外は、env:Body要素の構造を規定していません。いくつかのアプリケーションは、たとえば、"Example 1"にあるようにenv:Bodyの子要素をブロックに分けて構成しても良いです。しかし、これはSOAP処理モデルには関係がありません。

env:Body要素についてのその他の特徴的な役目である、SOAP仕様のフォルト(つまりSOAPメッセージの要素を処理する際の障害)に関する情報コンテナとしての役目については2.3 Faultシナリオですでに説明しました。

もしヘッダ要素が、値が"none"のenv:role属性をもっていたら、どのSOAPノードも内容を処理すべきでないことを意味しています。その内容が特定のSOAPノード宛の別のヘッダから参照されているデータで、あるノードがそれを調べる必要があったとしても、です。

もしenv:role属性の値が、つまり env:role="" のとき、それはロール(role)を示す相対URIが、問題のSOAPメッセージのベースURIで解決されなければならないことを意味しています。SOAP Version 1.2 は、SOAPメッセージのベースURIを定義していませんが、ベースURIを取得するためにに定義されているメカニズムに従います。そのメカニズムは、相対URIを絶対URIにするのに使えます。そのようなメカニズムは、プロトコルバインディングがベースURIを設定するためのもので、SOAPメッセージが包まれるプロトコルを参照することで可能でしょう。(実は、SOAPメッセージがHTTPを使って送られる場合、SOAP Part2 section 7.1.2 はベースURIをHTTPのリクエストURI、またはHTTP Content-Locationヘッダの値、と定義しています。

 

次の表は、色々なSOAPノードについて想定される、適用可能な標準化されたロール(role)をまとめたものです。(は該当のroleを担うことを示し、×は負わないことを示します。)

Role

ノード

指定なし "none" "next" "ultimateReceiver"
第一SOAP送信者 適用なし 適用なし 適用なし 適用なし
SOAP中継者 × × ×
最終SOAP受信者 ×

 


3.2 mustUnderstand属性

"Example 7b" は、"Example 7a"のヘッダブロックよりもう1つの(任意の)属性、 env:mustUnderstand属性が増えています。

Example 7b:  いろいろなヘッダブロックを含んだSOAPメッセージ
<?xml version="1.0" ?>
 <env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
   <env:Header>
     <p:oneBlock xmlns:p="http://example.com" 
            env:role="http://example.com/Log">
            env:mustUnderstand="true">
     ...
     ...
     </p:oneBlock>
     <q:anotherBlock xmlns:q="http://example.com"
       env:role="http://www.w3.org/2003/05/soap-envelope/role/next">
     ...
     ...
     </q:anotherBlock>
     <r:aThirdBlock xmlns:r="http://example.com">
     ...
     ...
     </r:aThirdBlock>
   </env:Header>
   <env:Body >
     ...
     ...
   </env:Body>
 </env:Envelope>

SOAPノードがenv:role属性を使って、自分のノードに宛てられたヘッダブロック(およびボディの場合も)を正しく見分けた後さらに行うべき処理については、ヘッダ要素のenv:mustUnderstand属性が決定します。SOAPノードがアプリケーション全体の目的に関して重要なヘッダブロックを無視しないことを確実にするために、SOAPヘッダブロックは任意の属性env:mustUnderstandを備えているのです。その値が"true"のときは、ターゲットのSOAPノードはそのブロックの仕様にしたがってブロックを処理しなくてはなりません。そのようなブロックは、(ぶっちゃけ)言ってしまえば、「必須ヘッダブロック」です。実は、自分のノード宛のすべての必須ヘッダブロックを識別・理解するまでは、SOAPメッセージの処理を開始してはいけないのです。ヘッダを理解する、ということはそのブロック仕様に何が記述されていたとしてもノードがしょりする準備をしなければならない、ということです。(なお、ヘッダフロックの仕様は、SOAP仕様外ということを覚えておいてください。)

"Example 7b" では、ヘッダブロックp:oneBlockは、env:mustUnderstandの値が"true"にセットされていますが、これはSOAPノードがenv:role="http://example.com/Log"で識別されるロール(role)を果たす場合は、このブロックの処理が必須だという意味です。他の2つのヘッダブロックは、そのようにセットされていないので、これらのブロックが宛てられた(ターゲットにされた)SOAPノードは、それらを処理する必要がありません。(おそらく、これら3つのブロックに関する仕様はそうすることを許しているでしょう。)

env:mustUnderstandの値が"true"のときは、SOAPノードはヘッダ仕様に記述された意味にあうようにヘッダの処理をしなくてはなりませんし、エラーが発生したときはSOAPフォールト(fault)を生成しなくてはなりません。ヘッダを処理する上では、SOAPメッセージからヘッダを削除したり、同じ値または違った値に変更したヘッダにしたり、新しいヘッダを挿入したりしても良いのです。必須ヘッダの処理ができないのであれば、SOAPメッセージのすべての処理を中止して、SOAPフォールトが生成されることが要求されます。そのメッセージはそれ以上(次のノードには)送信されません。

env:Body要素は、env:mustUnderstand属性を持っていませんが、最終SOAP受信者によって処理されなければなりません。"Example 7b" では、メッセージの最終受信者("ultimateReceiver"ロールを果たすSOAPノード)は、env:Bodyを処理しなくてはなりませんし、aThirdBlockを処理しても良いです。また、anotherBlockは、"next"が指定されているのでanotherBlockを処理しても良いですが、そのブロックの仕様で処理要求がなければ処理必須ではありません。(anotherBlockがnext(次の)受信者で処理されなければならないことを要求するときには、env:mustUnderstand="true"が指定されている必要があります。

SOAPメッセージを処理する際に、SOAPノードが果たすロールは色々な要因によって決められます。ロール(role)はすでに知られているのかもしれませんし、通信とは別の手段で設定されるのかもしれませんし、または期待されているロールを決定するためにノードが受信したメッセージのすべてを調べることができるのかもしれません。このロールの決定がいつされるとしても、外からはある処理モデルに基づいているように見えるに違いありません。つまり、メッセージ処理の開始時点からロールが知られているように見えなくてはならないのです。特に、外見上は、これらの付加ロールが期待されるヘッダのenv:mustUnderstandチェックは、処理開始前に実行されていなければなりません。また、SOAPノードがそのような付加ロールを想定するのなら、これらのロールに関する仕様が要求するすべてのことを行うための準備が確実にされなくてはなりません。

次の表は、env:mustUnderstand属性が示されたヘッダブロックが(env:role属性で)適切に示されたノードに関して、どう処理されるのかをまとめたものです。

ノード

mustUnderstand

中継ノード 最終受信ノード
"true" 処理しなければならない 処理しなければならない
"false" 処理しても良い 処理しても良い
指定なし 処理しても良い 処理しても良い

SOAPメッセージの処理に失敗したら、SOAPノードは1つのSOAPフォールトを生成するかもしれませんし、アプリケーションによっては、他のノードに宛てて追加のSOAPメッセージを生成するかもしれません。SOAP processing model はそのフォールとが生成される条件を定義していて、SOAP Part 1 section 5.4 はフォールトメッセージの構造を定義しています。2.3節で説明したように、SOAPフォールトはenv:Fault要素を含むenv:Body要素を持つSOAPメッセージです。

SOAPはフォールトを生成することと、フォールトがメッセージの生成者かこのフォールト情報から恩恵を得ることができるノードに確実に戻るようにすることとを区別しています。しかし、生成されたフォールトが適切に伝えられるかどうかはSOAPメッセージを交換するために選択された下位のプロトコルバインディングに依存します。仕様では、一方向のメッセージ伝送中にフォールトが生成されたときに何が起こるのかを定義していません。唯一の規範となるプロトコルバインディングであるSOAP HTTPバインディングは、送られてきたSOAPメッセージのフォールトを報告する手段として、HTTPレスポンスを提供しています。(SOAPプロトコルバインディングの詳細は4章を参照してください。)

 


3.3 relay属性

SOAP Version 1.2はヘッダブロックにもう1つの任意の属性、xs:boolean型のenv:relay属性、を定義しています。この属性は、SOAP中継者に宛てられたヘッダブロックが処理されなかったときに(次のノードに)中継されなければならないことを示します。

もしヘッダブロックが処理されたならば、SOAP処理ルール(SOAP Part 1 section 2.7.2を参照ください)は、そのヘッダブロックが(次のノードに渡される)メッセージから削除される、と規定していることに注意してください。(でも、他のヘッダブロックの処理で次のノードへのメッセージの中にそのヘッダブロックを保持するように決定したならば、内容はそのままか変更されて挿入されても良いです。) SOAP中継者が果たすロールに宛てたヘッダブロックが処理されなかったときのデフォルトの取り扱いは、メッセージが(次のノードに)中継される前に削除されなければならないことになっています。

デフォルト処理がそうなっている理由は、SOAP中継者がヘッダブロックがそれ以前のノードでどう処理されて自分に渡されたのかどうかを何も仮定していないとして安全性の面を考慮してのことです。そしてそのヘッダブロックが理解できず処理しないと選択したときには何らかの付加情報があることを示しています。それは、あるヘッダブロックがノードとノードの間の情報を表しているからで、端から端にそれに気づかずに伝えることは意味が無いかもしれないからです。あるSOAP中継者は、こうした決定をする役目に無いかもしれないので、処理されなかったヘッダブロックは、メッセージが次のノードに送り出される前に削除されたほうが安全と考えられました。

しかしながら、アプリケーション設計者が新しい機能を導入しようとしてSOAPヘッダブロックにそれを示し、それを処理可能なSOAPメッセージ経路上の任意の中継者に宛てて送る、という例があります。そうしたヘッダブロックは、それを理解できる中継者に適用できるのですが、それを理解できない中継者によって無視されて、メッセージが次のノードに中継されます。新しい機能として、このヘッダブロックを処理するソフトウェアが、少なくとも初めはすべてのノードではなく、一部のノードによって実装されるかもしれません。そうしたヘッダブロックでは、env:mustUnderstand="false"とすることが必要です。そうすることでその機能を実装していない中継者はフォールト(fault)を生成しないですみます。処理モデルのデフォルトルールを避けるために、ヘッダブロックに値が"true"env:relay属性を追加することで中継者が自分宛のヘッダブロックを処理できないと判断したときに次のノードに送ることができます。

"next"ロールの1つの期待される利用は、SOAPメッセージ経路全体を通じて情報を保持することですから、"next"ロールのノード宛てのヘッダブロックに値が"true"env:relay属性を付与することで、各中継者がヘッダを調べる機会を確実に提供することができます。もちろんアプリケーション設計者は常に特定の中継者に宛てたアプリケーション固有のロールを定義することができます。ですから、"none"や"ultimateReceiver"ロール以外のロールにenv:relay属性を使用する上では何の制約もありません。

"Example 7c" は、env:relay属性を使った例です。

Example 7c:  いろいろなヘッダブロックを含んだSOAPメッセージ。ヘッダブロックのひとつは処理できなかったときには次のノードに中継されなければなりません。
<?xml version="1.0" ?>
 <env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
   <env:Header>
     <p:oneBlock xmlns:p="http://example.com" 
           env:role="http://example.com/Log" 
               env:mustUnderstand="true">
     ...
     ...
     </p:oneBlock>
     <q:anotherBlock xmlns:q="http://example.com"
       env:role="http://www.w3.org/2003/05/soap-envelope/role/next"
       env:relay="true">
     ...
     ...
     </q:anotherBlock>
     <r:aThirdBlock xmlns:r="http://example.com">
     ...
     ...
     </r:aThirdBlock>
   </env:Header>
   <env:Body >
     ...
     ...
   </env:Body>
 </env:Envelope>

"next"ロールのノードに宛てたヘッダブロック、q:anotherBlockは、env:relay="true"の属性を持っています。このメッセージを受信したSOAPノードは、そのヘッダブロックが理解できたら処理しても良いですが、もし処理したら、処理ルール上はこのヘッダブロックはメッセージが次のノードに送られる前に削除されることになっています。しかし、その処理は必須ではありませんから、もしSOAPノードがこのヘッダブロックを無視することに決めたら、env:mustUnderstand"属性が無いので、次のノードに中継しなければなりません。

p:oneBlockヘッダブロックの処理は必須で、SOAP処理ルール上は、他のヘッダブロックの処理でそのヘッダブロックを次に渡すメッセージに含むことを要求しない限り次に中継されないことになっています。p:aThirdBlockヘッダブロックはenv:relay属性を持ってなくて、env:relay="false"と同じことです。ですから、このヘッダブロックは、処理されなかったときには次のノードには中継されません。

SOAP 1.2 Part 1 Table 3は、SOAP中継者が与えられたロールで未処理のヘッダブロックを次に中継可能かどうかの決定条件をまとめたものです。

【補足】"next"ロールのヘッダブロックが処理できなかったら、env:relay="true"のとき以外は次のノードに中継しない、と覚えておきましょう。細かいことはSOAP 1.2 Part 1 Table 3を参照してくださいね。

解説担当の「さら」です

 


4. 色々なプロトコルバインディングの使用

SOAPメッセージは、他のアプリケーションレイヤのプロトコルを含めて、色々な下位のプロトコルを使って交換されます。SOAPメッセージが、下位のプロトコルを使ってひとつのノードからもう一方のノードにどのように渡されるのかについての仕様は「SOAPバインディング」と呼ばれます。[SOAP Part1] はSOAPメッセージを [XMLインフォセット] の様式で定義しています。つまり、env:Envelopeと呼ばれるドキュメントの要素と属性の情報項目について定義しています。どのenv:Envelopeインフォセット表現も、プロトコルバインディング(の処理)によって具体的なものにされます。その処理では、情報の欠落がなくインフォセットの再構築が可能な方法でメッセージ経路上の次の(next)SOAPノードに運ばれる"インフォセットのシリアライズ表現"を提供することになっています。SOAPメッセージの典型的な例では、そしてこの入門編で示しているすべての例でも、整形式の(well-formed) [XML 1.0] ドキュメントです。でも、他のプロトコルバインディングもあり得ます。たとえば、通信バンド幅が狭いインターフェイス上の2つのSOAPノード間のプロトコルバインディングです。その場合は、同じインフォセットが圧縮シリアライズ処理されることが選択されるかもしれません。別の目的で選ばれたその他のバインディングでは、同じインフォセットが暗号化された構造データとしてシリアライズされるかもしれません。

SOAPメッセージ経路上の近接しているSOAPノード間のSOAPインフォセットの具体的な実装を提供するだけでなく、プロトコルバインディングはSOAPアプリケーションが必要とするSOAPフィーチャをサポートする手段を提供します。フィーチャはバインディングが提供する特定の機能についての仕様です。フィーチャの種類はURIで識別されますので、それを参照するすべてのアプリケーションは同じ意味を示していることが保証されます。たとえば、典型的な利用シナリオでは近接するSOAPノード間の多くのリクエスト-レスポンスの交換があり、その場合、要求されるフィーチャはリクエストとレスポンスを互いに関連させることができることです。他の例では、"暗号化されたチャネル"フィーチャや、"信頼される配送チャネル"フィーチャ、または"SOAPメッセージ交換パターンSOAP Message Exchange Patterns (MEPs)"フィーチャがあります。

SOAPバインディング仕様(SOAP Part 1 section 4を参照してください)は、どれがフィーチャを提供するかを記述しています。いくつかのフィーチャは下位のプロトコルが持っている機能で提供されるかもしれません。バインディングでは提供できない機能は、SOAPヘッダブロックを使って、SOAPエンベロープで実現されるかもしれません。SOAPヘッダブロックを使って実装された機能仕様は SOAPモジュールと呼ばれます。

たとえば、SOAPメッセージ交換がUDPのようなデータグラムプロトコルで行われていたら、明らかにメッセージの相互関連付けは、アプリケーションが直接に行うか、交換されているSOAPインフォセットの一部としてが良いでしょうが、(ともかく)別のところで提供されなくてはならないでしょう。後者の場合、メッセージの相互関連付けの機能は、SOAPエンベロープ内のバインディングに関する記述があります。つまり、SOAPヘッダブロックとしてURIで識別できる"リクエスト-レスポンスの関係"モジュールに記述されます。しかし、SOAPインフォセットが"リクエスト-レスポンス"のプロトコルを持つ下位プロトコルで交換されたら、アプリケーションはバインディングで提供されるこの機能を暗黙に利用でき、アプリケーションやSOAPレベルではそれ以上になにか提供しなくてはならないものはありません。(実際のところ、SOAPのHTTPバインディングでは、まさにHTTPのこの機能を利用しているのです。)

しかし、SOAPメッセージは送信者から最終受信者までいくつかのノード(原文ではhop)を経由することもありますし、各ノードはそれぞれ異なったバインディングを使っているかもしれません。言い換えると、あるノードのプロトコルバインディングで提供されているフィーチャ(たとえば、メッセージ間の関連付け、信頼性など)は、メッセージ経路の別のノードではサポートされていないかも知れないのです。SOAP自身は異なる下位プロトコルで提供されるフィーチャの違いを吸収するような手段を提供していません。しかしながら、特定のアプリケーションが必要している機能があって、それがメッセージ経路の(通信の)インフラで利用できないとしても、SOAPメッセージのインフォセットの一部として(つまりなんらかのモジュールにSOAPヘッダブロックとして)伝送されることで、その機能をカバーできるのです。

こんなふうにして、アプリケーションの目的を達成するためにアプリケーション設計者が取り組まなくてはならないいくつかの課題があるのは明らかです。それらの課題には、選択された環境で使用可能な下位プロトコルが持っている機能をどのように利用するか、ということも含まれます。SOAP Part 1 section 4.2は、アプリケーションの目的を達成するために、SOAPベースのアプリケーションが下位のプロトコルバインディングが提供しているフィーチャをどのように選択できるかを記述した汎用的なフレームワークを提供しています。それは、SOAPメッセージ交換のための相互に利用可能なプロトコルバインディング仕様を記述するためのガイドラインを提供しようとするものです。

バインディング仕様は、他の仕様とともにひとつの特定のフィーチャ、つまり、サポートするメッセージ交換パターンを定義しなければなりません。[SOAP Part2]は、次の2つのメッセージ交換パターンを定義しています。

  1. SOAP リクエスト-レスポンスメッセージ交換パターン: 近接するSOAPノード間でSOAPメッセージが交換されるパターン
  2. SOAPレスポンスメッセージ交換パターン: リクエストがSOAPメッセージではなく、レスポンスの一部にSOAPメッセージが返されるパターン

[SOAP Part2]はアプリケーション設計者に、SOAP Web Method featureと呼ばれる汎用的なフィーチャを提供しています。それは、いわゆる"Webメソッド"と呼ばれる、バインディングで利用できる[HTTP 1.1]仕様に定義されているGET, POST, PUT, DELETE のひとつをアプリケーションが自由に選択できるようになっています。このフィーチャは、SOAPを使用したアプリケーションがWorld Wide Webのアーキテクチャ・プリンシプルに準じたやり方できちんとできるようにするために定義されています。(ごく簡単に言いますと、Webの単純性と拡張性は、URIを通じてWeb上のどんなリソースもやりとりができるごくわずかの汎用的なメソッド(GET, POST, PUT, DELETE)があるという事に基づいています。) SOAP Webメソッドフィーチャは、HTTPバインディングでサポートされていますが、原則的にすべてのSOAPプロトコルバインディングで可能です。

SOAP Part 2 section 7は、[SOAP Part1]のバインディングフレームワークを使った標準化されたプロトコルバインディング、つまりSOAPをHTTPプロトコルとどう関連付けるかについて、を記述しています。SOAP Version 1.2はHTTPバインディングでPOSTをリクエスト-レスポンスメッセージ交換パターンと、GETをSOAPレスポンスメッセージ交換パターンとを対応付けるように制限しています。将来的には他の仕様で、HTTPや他のWebメソッド(たとえば、PUT, DELETE)を使用したそのたのトランスポートのSOAPバインディングを定義するかもしれません。

次の節では、2つの下位プロトコルバインディング、つまり[HTTP 1.1]と電子メール、の例を紹介します。SOAP 1.2メッセージの標準のバインディングは[HTTP 1.1]だということが強調されます。4.2節の例は、SOAPメッセージの送信手段としての電子メールを紹介しますが、SOAPメッセージを伝送するための、標準化がされていない他の選択肢を示しているだけです。 W3C Note の[SOAP電子メールバインディング]では、[SOAP Part1]のSOAPプロトコルバインディングのアプリケーションに[RFC 2822]ベースのメッセージ伝送の電子メールトランスポートについての情報を提供しています。

 


4.1 SOAP HTTPバインディング

HTTPはよく知られた接続モデルとメッセージ交換パターンを持っています。クライアントはURIでサーバを特定し、TCP/IPを使ってそのサーバに接続し、HTTPリクエストメッセージを発行、HTTPレスポンスを受取ります。HTTPは暗黙的にリクエストメッセージをレスポンスメッセージと関連付けています。ですから、HTPPバインディングを使うアプリケーションは、HTTPリクエストメッセージのボディ(body)で送られたSOAPメッセージとHTTPレスポンスに含まれるSOAPメッセージが関連していると見なすことができます。同様に、HTTPはサーバをURIで識別し、Request-URIでサーバのSOAPノードを識別します。

HTTPではクライアントとRequest-URIで指定されたサーバとの間に複数の中継者があっても良く、その場合、リクエスト/レスポンスモデルがつながった形になります。でも、HTTPの中継者はSOAP中継者とは違うので注意しましょう。

[SOAP Part2]のHTTPバインディングは、HTTPメッセージ交換にアプリケーションがいわゆるWebメソッド(GETかPOSTに限定されますが)をできるようにSOAP Webメソッドを利用します。さらにHTTPバインディングは、アプリケーションがHTTPを使ってSOAPメッセージを交換できるように、次の2つのメッセージ交換パターンを利用します。

  1. HTTP POSTメソッドを使用して、HTTPリクエスト/レスポンスメッセージのボディ(body)でSOAPメッセージを運ぶ
  2. HTTP GETメソッドを使用してHTTPリクエストを送り、HTTPレスポンスのボディ(body)でSOAPメッセージを返す
1)のパターンは、SOPAリクエスト・レスポンス交換パターンと呼ばれるのHTTP特有のバインディングで、2)のパターンはSOAPメッセージ交換パターンと呼ばれるバインディングです。

これら2つの利用タイプを提供する目的は、2つの相互作用の規範をWorld Wide Web上にうまく作り上げることです。相互作用の最初のタイプは、URIで識別されHTTPリクエストの宛先になっているリソースの状態を、HTTP POSTのボディに含まれるデータを使って生成したり変更したりできる様にします。2つ目のタイプは、HTTP GETリクエストを使って、リソースの状態を変更しないでリソースからデータを得ることができる様にします。最初のケースでは、SOAPの視点での関心事は、HTTP POSTリクエストのボディがPOSTに準拠しアプリケーション固有の処理の一部として(SOAP処理モデルによって)処理されなければならないSOAPメッセージだということです。2つ目のケースでは、予想される典型的な利用は、リクエストされたリソースから得られるデータがHTMLやXMLデータではなく、SOAPメッセージというケースです。つまり、レスポンスメッセージのHTTPコンテントタイプヘッダのメディアタイプが"application/soap+xml"でそれを示しています。SOAPメッセージの形式でデータを取得できるようにWeb上にリソースを公開するものもでてくるでしょう。でも、そのリソースは一般には複数のデータ表現を持つことができますし、要求されるか好ましいデータ表現は、リクエストしているアプリケーションによってHTTPアクセプトヘッダを使って指定されることに注意してください。

さらにSOAP HTTPバインディングについて見なくてはいけないのは、アプリケーションがこれら2つのメッセージ交換タイプのいずれを使用するかをどのように決定するかという問題です。[SOAP Part2]はアプリケーションが2つのメッセージ交換パターンのいずれかを使用する際の環境についてのガイドを提供しています。(それは、"MUST"ではなく最も強い"SHOULD"と表現されているガイドです。これらの用語はIETF [RFC 2119]に規定されています。) HTTP GETメソッドを伴うSOAPレスポンスメッセージパターンは、アプリケーションがリソースとの相互作用の結果として情報リソースには一切触れないで情報を取得する目的でメッセージ交換をする時に使用されます。そうした相互作用は、HTTP仕様で安全かつ副作用の無いメソッドと記述されています。HTTP SOAP GETの使用では、リクエストにSOAPメッセージを使えないので、SOAPインフォセット(つまりSOAPヘッダブロック)に含まれるバインディング仕様の記述でサポートされる相互作用を必要とするアプリケーションは、明らかにこのメッセージ交換パターンを使えません。HTTP POSTバインディングはすべてのケースで使用可能なことを知っておきましょう。

以下に、HTTPバインディング用に定義された2つのメッセージ交換パターンのexampleを示します。

4.1.1 SOAP HTTP GETの使用

SOAPレスポンスメッセージ交換パターンのHTTPバインディングは、HTTP GETメソッドに限られます。これは、HTTP GETリクエスト先のSOAPノードから帰ってくるレスポンスは、HTTPレスポンスに含まれるSOAPメッセージということです。

Example 8a は、(旅行予約のシナリオで)旅行アプリケーションから、URI http://travelcompany.example.org/reservations?code=FT35ZBQ に発行されたHTTP GETです。(このURLがどのようにして作成可能かは、Example 5aを参照してください。)

Example 8a:  HTTP GETリクエスト
GET /travelcompany.example.org/reservations?code=FT35ZBQ  HTTP/1.1
Host: travelcompany.example.org
Accept: text/html;q=0.5, application/soap+xml

HTTP Acceptヘッダは、リクエスト先のリソースに望むデータ表現を示すのに使われます。この例では、人がブラウザで見るための"text/html"メディアタイプではなく、プログラムのための"application/soap+xml"メディアタイプが指定されています。

Example 8b は、Example 8a のGETリクエストへのHTTPレスポンスを示しています。HTTPレスポンスのボディ(body)は、旅行の詳細を示すSOAPメッセージを含んでいます。SOAPメッセージの内容については、HTTP GETバインディングを理解することとは関連が無いので、5.2節までおあずけにします。

Example 8b:  Example 8a のGETリクエストへのHTTPレスポンス
HTTP/1.1 200 OK
Content-Type: application/soap+xml; charset="utf-8"
Content-Length: nnnn

<?xml version='1.0' ?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"> 
 <env:Header>
  <m:reservation xmlns:m="http://travelcompany.example.org/reservation" 
       env:role="http://www.w3.org/2003/05/soap-envelope/role/next"
           env:mustUnderstand="true">
   <m:reference>uuid:093a2da1-q345-739r-ba5d-pqff98fe8j7d</m:reference>
   <m:dateAndTime>2001-11-30T16:25:00.000-05:00</m:dateAndTime>
  </m:reservation>
 </env:Header>
 <env:Body>
  <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
            xmlns:x="http://travelcompany.example.org/vocab#"
     env:encodingStyle="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
   <x:ReservationRequest 
 rdf:about="http://travelcompany.example.org/reservations?code=FT35ZBQ">
      <x:passenger>ナke Jgvan リyvind</x:passenger>
      <x:outbound>
       <x:TravelRequest>
        <x:to>LAX</x:to>
        <x:from>LGA</x:from>
        <x:date>2001-12-14</x:date>
       </x:TravelRequest>
      </x:outbound>
      <x:return>
       <x:TravelRequest>
        <x:to>JFK</x:to>
        <x:from>LAX</x:from>
        <x:date>2001-12-20</x:date>
       </x:TravelRequest>
      </x:return>
    </x:ReservationRequest>
  </rdf:RDF>
 </env:Body>
</env:Envelope>

予約の詳細は、(X)HTMLドキュメントとして戻されても良いのですが、この例では、ブラウザで処理されることよりも、プログラムで処理可能なデータ中心の形式(SOAPメッセージ)で予約アプリケーションがリソース(予約のこと)の状況を戻しているケースを示したい、ということに注意してください。実際に、最もありそうなSOAPの利用では、それを利用するアプリケーションはブラウザではないのです。

また、この例に示すように、HTTPレスポンスボディにSOAPを利用することで、SOAPヘッダを通じてアプリケーション固有の情報や機能を表現することができます。SOAPを使うことで、アプリケーションはそうした機能のために有用で一貫したフレームワークと処理モデルを得ることができるのです。

4.1.2 SOAP HTTP POSTの使用

SOAPリクエスト・レスポンスメッセージ交換パターンのHTTPバインディングは、HTTP POSTメソッドに限られます。SOAP HTTPバインディングでのこのメッセージ交換パターンの使用は、SOAPメッセージで一般的なXMLデータやRPCの交換をするようなすべてのアプリケーションに適用可能だということを知っておきましょう。

Examples 9 と Example 10は、SOAPリクエスト・レスポンスメッセージ交換パターンを使ったHTTPバインディングの例を示しています。それぞれは、Example 4 と Example 5a で示したのと同じシナリオとなっています。つまり、RPCとそのリターンがSOAPメッセージのボディに含まれています。これらの例について、本節ではHTTPヘッダとその役割について説明します。

Example 9:  Example 4 のRPCをHTTP POSTリクエストで送信
POST /Reservations HTTP/1.1
Host: travelcompany.example.org
Content-Type: application/soap+xml; charset="utf-8"
Content-Length: nnnn

<?xml version='1.0' ?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" >
  <env:Header>
   <t:transaction
     xmlns:t="http://thirdparty.example.org/transaction"
     env:encodingStyle="http://example.com/encoding"
     env:mustUnderstand="true" >5</t:transaction>
   </env:Header>  
   <env:Body>
     <m:chargeReservation 
     env:encodingStyle="http://www.w3.org/2003/05/soap-encoding"
     xmlns:m="http://travelcompany.example.org/">
     <m:reservation xmlns:m="http://travelcompany.example.org/reservation">
	 <m:code>FT35ZBQ</m:code>
     </m:reservation>    
     <o:creditCard xmlns:o="http://mycompany.example.com/financial">
     <n:name xmlns:n="http://mycompany.example.com/employees">
           Ake Jogvan Olyvind
     </n:name>    
     <o:number>123456789099999</o:number>
     <o:expiration>2005-02</o:expiration>
    </o:creditCard>
   </m:chargeReservation>
  </env:Body>
</env:Envelope>

Example 9 は旅行サービスアプリケーション宛のRPCリクエストです。SOAPメッセージは、travelcompany.example.orgサーバ上の"Reservations"リソースを識別するURI宛てにHTTP POSTメソッドのボディ(body)で送られます。HTTPを使うとき、リクエストURIは、リクエストが渡されるリソースを示しています。妥当なURIでなければならないこと以外は、SOAPはリクエストURI(URIについては、 [RFC 2396] を参照してください)の形式については何の制約もしていません。しかし、Webアーキテクチャの原則のひとつに、「すべての重要なリソースはURIで識別されなければならない」ということがあります。このことは、最もよく設計されたSOAPサービスは、各々がURIを持っている非常に多くのリソースを備えていることを意味しています。実際には、例にあるように特定の予約などのように、多くのリソースはサービスの処理で動的に生成されているようです。ですから、よく設計された旅行サービスアプリケーションは、各予約について異なるURIを持っていなくてはなりませんし、予約を取り出したり操作するためのSOAPリクエストはそれらのURIに対して発行され、Example 9 に示されるようにひとつの"Reservations" URIに宛てられるものではありません。4.1.3節のExample 13 は、そうした特定の旅行予約リソース宛にリクエストされるより好ましい方法を示しています。ですから、Webアーキテクチャに適合したSOAP/HTTPの使用についてお話します。

HTTPボディにSOAPメッセージを置いたとき、HTTPのContent-typeヘッダは、"application/soap+xml"でなければなりません。(例に示すように、オプションの charsetパラメタは、"utf-8" か "utf-16"ですが、もしcharsetパラメタの指定が無い場合、 [XML 1.0] のcharsetルールがHTTPリクエストのボディに適用されます。)

Example 10 は、Example 5a のリクエストに対する旅行サービスアプリケーションからのRPCリターンを示しています(詳細は省略してます)。HTTPを使ったSOAPは、HTTPの通信ステータス用のHTTPステータスコードに続いてます。たとえば、2xxシリーズのHTTPステータスは、クライアントのリクエストが(SOAPの部分を含めて)正常に受信・理解・受付け等されたことを示しています。

Example 10:  成功を示すHTTPレスポンスに含まれるExample 5a のRPCリターン
HTTP/1.1 200 OK
Content-Type: application/soap+xml; charset="utf-8"
Content-Length: nnnn

<?xml version='1.0' ?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" >
 <env:Header>
       ...
       ...
 </env:Header>  
 <env:Body>
       ...
       ...
 </env:Body>
</env:Envelope>

HTTPバインディング仕様では、もしリクエスト処理でエラーが発生したら、サーバ側の処理エラーを示すSOAP Faultを含むSOAPメッセージを伴ってHTTP 500 "Internal Server Error" が使用されるよう規定しています。

Example 11 は、Example 6aと同じSOAP Faultを示していますが、HTTPヘッダが追加されています。

Example 11:  Example 4 のSOAPボディの処理エラーを示すHTTPレスポンスに含まれるSOAPメッセージ
HTTP/1.1 500 Internal Server Error
Content-Type: application/soap+xml; charset="utf-8"
Content-Length: nnnn

<?xml version='1.0' ?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
  <env:Body>
    <env:Fault>
     <env:Code>
       <env:Value>env:Sender</env:Value>
       <env:Subcode>
        <env:Value>rpc:BadArguments</env:Value>
       </env:Subcode>
     </env:Code>
     <env:Reason>
      <env:Text xml:lang="en-US">Processing error</env:Text>
      <env:Text xml:lang="cs">Chyba zpracov疣</env:Text>
     </env:Reason>
     <env:Detail>
      <e:myFaultDetails 
        xmlns:e="http://travelcompany.example.org/faults" >
        <e:message>Name does not match card number</e:message>
        <e:errorcode>999</e:errorcode>
      </e:myFaultDetails>
     </env:Detail>
   </env:Fault>
 </env:Body>
</env:Envelope>

SOAP Part 2 Table 16 は、色々とありうるHTTPレスポンスコード、つまり 2xx (successful) 3xx (redirection)4xx (client error)5xx (server error)の詳細な取り扱いについて記述しています。

4.1.3 Webアーキテクチャに適合したSOAPの使用

World Wide Webの最も中心的な概念のひとつは、リソース識別子としてのURIです。HTTPバインディングを使用し、他のWebサービスと相互に効果的に動作しようとするSOAPサービスは、そのサービスのすべての重要なリソースを指し示すのにURIを使わなくてはなりません。たとえば、とても重要なWorld Wide Webの使用は純粋に情報の取得で、URIで特定される利用可能なリソースの内容は、リソースに影響を与えることのないHTTP GETリクエストを使って取り出されます。(これは、HTTP用語でsafe and idempotent method(安全で、べき等な方法)と呼ばれます。)キーポイントは、リソースを公開(発行)者は、利用者が"GET"できるようにそのURIを有効にしなければならない、ということです。

「べき等」とは、同じ操作を何度繰り返しても同じ結果になる、というような意味です。

リソースの操作ではなくリソース(プログラム用語ではオブジェクトと言ったりします)の状態が要求されたりするような、純粋に情報を取得するためにSOAPメッセージが設計される実例がたくさんあります。そうした例では、ボディの要素がオブジェクトに問合せしていることを示すようにしてSOAPボディの使用することは、HTTP GETのリクエストURIでリソースが示されていないのでWebの精神に反しているようにみられます。(いくつかのSOAP/RPCの実装では、HTTPリクエストURIはしばしばリソースの識別子ではなく、リソースを特定するためにSOAPメッセージを評価しなければならない中間的なエンティティを示しています。)

変更が必要とされるのを強調するために、Example 12a はWeb上で安全に情報を取得するのに推奨されない方法を示しています。これは旅行予約について再度採り上げていますが、ひとつのパラメタreservationCodeで識別される特定の予約の旅行日程を取得するリクエストがSOAPメッセージで送信されるRPCの例です。(ここでの説明のために、このアプリケーションはSOAPヘッダが必要でないRPCリクエストを使っていると想定しています。)

Example 12a:  リソースに対する操作が安全な(リソースに副作用の無い)情報取得にはならないケースを示しています。
POST /Reservations HTTP/1.1
Host: travelcompany.example.org
Content-Type: application/soap+xml; charset="utf-8"
Content-Length: nnnn

<?xml version='1.0' ?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" >
  <env:Body>
    <m:retrieveItinerary 
        env:encodingStyle="http://www.w3.org/2003/05/soap-encoding"
             xmlns:m="http://travelcompany.example.org/">
      <m:reservationCode>FT35ZBQ</m:reservationCode>
    </m:retrieveItinerary>
  </env:Body>
</env:Envelope>

取得されるリソースがHTTPリクエストのターゲットURIで示されないで、SOAPエンベロープ中を見て分かることに注意してください。このように、Web上の他の"GET"できるURIの場合ではできないことを、World Wide Web上の利用者がHTTPだけを使ってできるようにしています。

SOAP Part 2 section 4.1は、安全でべき等な情報の取得をするRPCをWebに親和性があるにはどうしたらいいかについて推奨する方法を示しています。それは、RPC定義に含まれるメソッドと特定のパラメタに関して、リソースを識別する目的とそのほかの目的とを区別することです。Example 12a では、取得されるリソースは2つの項目から識別されています。1つ目は、itinerary(メソッド名の一部)で、2つ目は特定のインスタンスへの参照(メソッドへのパラメタ)です。そのような場合に推奨されるのは、たとえば次のようなURIのように、リソースを識別するHTTPリクエストURIにこれらのリソースを識別する項目が含められることです。
http://travelcompany.example.org/reservations/itinerary?reservationCode=FT35ZBQ

さらに、RPC定義がそのメソッド記述のすべての項目がリソースを識別するもののような場合、RPCのすべてのターゲットはURIで識別できます。この場合、もしリソース提供者が、取得リクエストが安全なものだと確信できるのなら、SOAP Version 1.2 はGETメソッドを使って、4.1.1節で説明したSOAPレスポンスメッセージ交換パターンを使うことを推奨しています。これによってSOAP RPCがWebのアーキテクチャに準じたやり方で実行されます。Example 12b は、SOAPノードがリソースを安全に取得リクエストするための好ましい方法を示しています。

Example 12b:  Example 12a のRPCをWebのアーキテクチャに準じたやり方で示した例
GET /Reservations/itinerary?reservationCode=FT35ZBQ  HTTP/1.1
Host: travelcompany.example.org
Accept: application/soap+xml

SOAP Version 1.2 は、情報取得のために決められたRPCの定義からURIを算出するアルゴリズムについては規定していないことに注意してください。

でも、アプリケーションがSOAPインフォセット内にバインディングに関する記述を持つ機能を使うこと、つまりSOAPヘッダブロックを使うことを要求したときには、アプリケーションはリクエストボディのSOAPメッセージを送るのに HTTP POSTメソッドを選択しなくてはならないことは覚えておきましょう。

RPC記述がリソースを識別しないデータ(パラメタ)を含んでいる場合、SOPAリクエスト・レスポンスメッセージ交換パターンを使用することも要求されます。このようなケースでも、SOAPメッセージを伴うHTTP POSTはWebに親和性のあるやり方で表現することができます。GETの使用について、[SOAP Part2]は、リクエストがPOSTされるリソースを識別するものがSOAPメッセージのどの箇所にあっても、HTTPリクエストURI中で識別されるように、一般的なケースに関して推奨しています。もちろん同じパラメタは、SOAPのenv:Body要素内にあってもかまいません。(メッセージを受取るアプリケーションが期待しているプロシジャ/メソッド記述に関するSOAPベースのRPCの場合は、パラメタはBody内になくてはなりません。)

Example 13 は Example 9 と同じですが、HTTPリクエストURIがリソース(確認・支払のために問い合わせしているreservation)を識別するための reservation code を含むように変更されています。

Example 13:  Example 4のRPCをWebに親和性のあるHTTPリクエストで送信する例
POST /Reservations?code=FT35ZBQ HTTP/1.1
Host: travelcompany.example.org
Content-Type: application/soap+xml; charset="utf-8"
Content-Length: nnnn

<?xml version='1.0'?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" >
 <env:Header>
   <t:transaction
           xmlns:t="http://thirdparty.example.org/transaction"
           env:encodingStyle="http://example.com/encoding"
           env:mustUnderstand="true" >5</t:transaction>
 </env:Header>  
 <env:Body>
  <m:chargeReservation
      env:encodingStyle="http://www.w3.org/2003/05/soap-encoding"
         xmlns:m="http://travelcompany.example.org/">
   <m:reservation xmlns:m="http://travelcompany.example.org/reservation">
    <m:code>FT35ZBQ</m:code>
   </m:reservation>
  <o:creditCard xmlns:o="http://mycompany.example.com/financial">
    <n:name xmlns:n="http://mycompany.example.com/employees">
           Ake Jogvan Olyvind
    </n:name>
    <o:number>123456789099999</o:number>
    <o:expiration>2005-02</o:expiration>
   </o:creditCard>
  </m:chargeReservation>
 </env:Body>
</env:Envelope>

Example 13 では 操作されるリソースは2つの項目で識別されます。1つ目はreservation(メソッド名の一部)で、2つ目はreservationのインスタンス(メソッドへのcodeパラメタの値)です。RPCの残りのパラメタ、たとえばcreditCard番号はリソース識別子ではありませんが、リソースで処理される付属的なデータです。 SOAP-based RPCがアクセスできるリソースは、RPCのターゲットを識別するURIの一部としてリソースを識別するための情報を置かなくてはならない、というのが[SOAP Part2]での勧告です。でも、[SOAP Part2]はそれについて何らのアルゴリズムを提供していないことに注意しなくてはなりません。それでも、すべてのリソース識別要素は Example 9に見るように、SOAPのenv:Body要素のデータに含まれていましたね。

言い換えると、上の例に見るように、SOAP仕様の勧告は Webアーキテクチャに準じた方法で、つまりGETでもPOSTでもリソース識別子として、URIを使用することだといえます。


4.2 EMailでSOAP

アプリケーション開発者は電子メールのテキストや添付データとしてSOAPメッセージを送るために、電子メールインフラを使うことができます。次の例は、標準的な方法と思っていただいてはいけないのですが、SOAPメッセージを送るひとつの方法を示しています。SOAPバージョン1.2の仕様ではそのようなバインディングは規定していません。でも、基準ではないW3C Note [SOAP Emial Binding]ではSOAPの電子メールバインディングについて述べていますが、その目的は [SOAP Part 1]で述べられている一般的なSOAPプロトコルバインディングフレームワークのアプリケーションを示すためです。

Example 14 は、送信・受信メールエージェント間で送られる電子メールメッセージとして運ばれる、Example 1の旅行予約リクエストメッセージを示しています。受信ノードは、電子メールボディのSOAPを処理できると想定してます。(送信ノードもまた、レスポンスとしてどんなSOAPメッセージを受取っても、どんなSOAPフォルトが戻ってきても対応できるものと想定しています。)

Example 14:  Example 1のSOAPメッセージをSMTPで送信する例
From: a.oyvind@mycompany.example.com
To: reservations@travelcompany.example.org
Subject: Travel to LA
Date: Thu, 29 Nov 2001 13:20:00 EST
Message-Id: <EE492E16A090090276D208424960C0C@mycompany.example.com>
Content-Type: application/soap+xml 

<?xml version='1.0' ?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"> 
 <env:Header>
  <m:reservation xmlns:m="http://travelcompany.example.org/reservation" 
      env:role="http://www.w3.org/2003/05/soap-envelope/role/next"
         env:mustUnderstand="true">
   <m:reference>uuid:093a2da1-q345-739r-ba5d-pqff98fe8j7d</reference>
   <m:dateAndTime>2001-11-29T13:20:00.000-05:00</m:dateAndTime>
  </m:reservation>
  <n:passenger xmlns:n="http://mycompany.example.com/employees"
      env:role="http://www.w3.org/2003/05/soap-envelope/role/next"
         env:mustUnderstand="true">
   <n:name>ナke Jgvan リyvind</n:name>
  </n:passenger>
 </env:Header>
 <env:Body>
  <p:itinerary 
     xmlns:p="http://travelcompany.example.org/reservation/travel">
   <p:departure>
     <p:departing>New York</p:departing>
     <p:arriving>Los Angeles</p:arriving>
     <p:departureDate>2001-12-14</p:departureDate>
     <p:departureTime>late afternoon</p:departureTime>
     <p:seatPreference>aisle</p:seatPreference>
   </p:departure>
   <p:return>
     <p:departing>Los Angeles</p:departing>
     <p:arriving>New York</p:arriving>
     <p:departureDate>2001-12-20</p:departureDate>
     <p:departureTime>mid morning</p:departureTime>
     <p:seatPreference/>
   </p:return>
  </p:itinerary>
  <q:lodging 
     xmlns:q="http://travelcompany.example.org/reservation/hotels">
   <q:preference>none</q:preference>
  </q:lodging>
 </env:Body>
</env:Envelope>

Example 14 のヘッダは電子メールメッセージのための標準形式 [RFC 2822] に示されています。

電子メールは一方向のメッセージ交換で、配達完了の保証もありませんが、[SMTP(Simple Mail Transfer Protocol)] 仕様のような電子メールのインフラは配達完了の通知メカニズムを提供しています。SMTPの場合は、DSN(Delivery Status Notification: 配信状態通知)とMDN(Message Disposition Notification: メッセージ開封確認通知)と呼ばれています。これらの通知は、メールヘッダに指定された電子メールアドレスに送られる電子メールメッセージのの形式をとります。電子メールのエンドユーザだけでなく、アプリケーションも電子メール送信状態を示すためにこれらのメカニズムを使うことができます。でも、これらが配達されたとしても、SMTPレベルの通知なのです。アプリケーション開発者は、これらの配達通知の能力や制限について充分理解していなければなりません。もしくは、何も起こらなかったときに、データ配達が成功したと想定してしまうリスクについても理解しておかなくてはなりません。

SMTP配達状態メッセージは、SOAPレイヤのメッセージ処理とは区別されます。含まれたSOAPメッセージに対する結果のSOAPレスポンスは、新しい電子メールメッセージを通じて返されます。その新しいメッセージは、SMTPレベルの元のリクエスト電子メールへのリンクを含んでいてもいなくてもかまいません。[RFC 2822]にあるIn-reply-to:ヘッダを使えばSMTPレベルでのメッセージの関連付けができますが、必ずしもSOAPレベルの関連付けをするものではありません。

Example a5 はExample 2で示したものと同じシナリオのもので、旅行サービスアプリケーションから旅行予約アプリケーション宛に(ここでは電子メールメッセージとして送られる)予約の詳細情報を要求するSOAPメッセージ(説明を簡潔にするためにbodyの詳細は省略)を示しています。)。この例では、元の電子メールのMessage-Idが追加された電子メールヘッダIn-reply-to:に含まれていてSMTPレベルでの電子メールメッセージを関連付けしていますが、SOAPレベルの関連は示していません。この例では、アプリケーションは、SOAPメッセージの関連付けにreservationヘッダブロックを使っています。再度確認しますが、そうしたメッセージの関連性はアプリケーションに依存していて、SOAP仕様では関知していません。

Example 15:  先のメッセージへの関連付け情報をヘッダに持っている電子メールメッセージでExample 2のSOAPメッセージを送信する例
From: reservations@travelcompany.example.org
To: a.oyvind@mycompany.example.com
Subject: Which NY airport?
Date: Thu, 29 Nov 2001 13:35:11 EST
Message-Id: <200109251753.NAA10655@travelcompany.example.org>
In-reply-to:<EE492E16A090090276D208424960C0C@mycompany.example.com>
Content-Type: application/soap+xml

<?xml version='1.0' ?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"> 
 <env:Header>
  <m:reservation xmlns:m="http://travelcompany.example.org/reservation" 
     env:role="http://www.w3.org/2003/05/soap-envelope/role/next"
       env:mustUnderstand="true">
   <m:reference>uuid:093a2da1-q345-739r-ba5d-pqff98fe8j7d</reference>
   <m:dateAndTime>2001-11-29T13:35:00.000-05:00</m:dateAndTime>
  </m:reservation>
  <n:passenger xmlns:n="http://mycompany.example.com/employees"
      env:role="http://www.w3.org/2003/05/soap-envelope/role/next"
        env:mustUnderstand="true">
   <n:name>ナke Jgvan リyvind</n:name>
  </n:passenger>
 </env:Header>
 <env:Body>
  <p:itinerary
     xmlns:p="http://travelcompany.example.org/reservation/travel">
   <p:itineraryClarifications>
      ...
      ...
   </p:itineraryClarifications>
  </p:itinerary>
 </env:Body>
</env:Envelope>

 


5. 発展的利用シナリオ

5.1 SOAP中継者を使う

本書(このチュートリアルのこと)で使っている旅行予約シナリオでSOAP中継者を使用した例を示します。基本的なメッセージ交換は、旅行予約アプリケーションと旅行サービスアプリケーション間の旅行予約リクエストの交換でしたね。SOAPは、そのメッセージパスがどのように決められてどのようにたどられるのか、については規定していません。それはSOAP仕様外のことです。でも、もし最終受信者でないSOAPノードがSOAPメッセージを主審したときに、そのSOAPノードがどう取り扱わなければならないことについては述べています。SOAPバージョン1.2は、2つの中継者タイプ、転送中継者動的中継者について述べています。

転送中継者は、SOAPメッセージのヘッダブロックが示す意味やメッセージ交換パターンに基づくSOAPノードで、SOAPメッセージを他のSOAPノードに転送します。たとえば、受信したSOAPメッセージに含まれるメッセージ経路を示した"routing"ヘッダブロックを処理すると、そのヘッダブロックのデータで識別されるSOAPノードにメッセージが転送されるように示されているかもしれません。(そのSOAPノードによって)送り出されるSOAPメッセージのSOAPヘッダブロックのフォーマットは、つまり挿入/再挿入されるヘッダブロックの配置は、処理されたヘッダブロックが示す意味に基づいたこの転送中継者での総合的な処理によって決定されます。

動的中継者はSOAPメッセージを転送する前に、受信したSOAPヘッダブロックに記述されている情報やメッセージ交換パターンに依らない基準に基づいて付加的な処理をするSOAPノードです。動的中継者の例としては、たとえばSOAPメッセージの一部を暗号化したり、ヘッダブロックに暗号を解く鍵の情報を載せたりします。また、送り出すメッセージの追加した新しいヘッダブロックに、たとえばメッセージ経路上の適切なノードによって解釈されるようなタイムスタンプや注記などの付加情報を入れるかもしれません。

動的中継者がメッセージに加えられた変更を記述するためのメカニズムのひとつは、(その動的中継者によって)送り出されるSOAPメッセージにヘッダブロックを挿入することです。これらのヘッダブロックは、(メッセージ経路上の以降の)SOAPノードに正しい操作を行えるように知らせることができます。この場合、挿入されたヘッダブロックが示す意味は、(メッセージ経路上の以降の)SOAPノードによって安全に処理されることを確実にするために、このあとに続いている中継者でそれと同じか再挿入される別のヘッダブロックを要求してなければなりません。たとえば、暗号化のために削除されたヘッダブロックがあるメッセージが(もとのヘッダブロックが復号化・再構成されずに)第2の中継者を通ったとすると、暗号化されたことを示す情報は中継された次のメッセージ中に保持されなければなりません。

次の例では、旅行予約アプリケーションと旅行サービスアプリケーション間のメッセージ経路中にSOAPノードがあるものとします。そのノードはExample 1で示したメッセージを中継します。そのSOAPノードは、トラベルオフィスがオフラインで見れるように、すべての旅行リクエストのログを取得します。例にあったreservationpassengerヘッダブロックは、"next"ロールを持つノードに宛てられたものでしたね。(mustUnderstand属性は"true"に設定されている)ヘッダブロックは必須で、(ヘッダブロックが持つ意味とは別の仕様によって)ノードは何をすべきかを知っていなければなりません。そうしたヘッダブロックのログに関する仕様は、メッセージの詳細情報がすべてのノードで記録されることと、メッセージ経路に沿ってメッセージが変更されずに中継されることを単に要求しているのかもしれません。(ヘッダブロックの仕様はノードから次に渡されるメッセージに同じヘッダブロックがあることを要求しなければなりません。でないと、SOAP処理モデルはそれらが削除されることを要求するかもしれませんから。)この場合、SOAPノードは転送中継者として動作します。

もっと複雑なシナリオでは、第一SOAP送信者が期待していないような形でSOAPメッセージが修正されます。次の例では、SOAP中継者に存在する旅行アプリケーションが、最終受信者である旅行サービスアプリケーションに向けてメッセージを送り出す前にExample 1のSOAPメッセージにヘッダブロックを付加します。ヘッダブロックは、リクエストされた旅行に関する旅行ポリシーによる制約を含んでいます。そのようなヘッダブロックは、最終受信者(role属性が無いので最終受信者だけ)がメッセージのボディを処理するときにその情報を利用することを要求するかもしれません。

Example 16 は、動的中継者がtravelPolicyという付加ヘッダブロックを挿入しているものを示しています。それは、最終受信者宛てにアプリケーションレベルのこの旅行リクエスト処理に適切な情報を含んでいます。

Example 16:  旅行予約のためのExample 1のSOAPメッセージに、動的中継者が最終受信者宛に必須ヘッダブロックを挿入した例
<?xml version='1.0' ?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"> 
 <env:Header>
  <m:reservation xmlns:m="http://travelcompany.example.org/reservation" 
     env:role="http://www.w3.org/2003/05/soap-envelope/role/next"
        env:mustUnderstand="true">
   <m:reference>uuid:093a2da1-q345-739r-ba5d-pqff98fe8j7d</reference>
   <m:dateAndTime>2001-11-29T13:20:00.000-05:00</m:dateAndTime>
  </m:reservation>
  <n:passenger xmlns:n="http://mycompany.example.com/employees"
     env:role="http://www.w3.org/2003/05/soap-envelope/role/next"
       env:mustUnderstand="true">
   <n:name>Ake Jogvan Oyvind</n:name>
  </n:passenger>
  <z:travelPolicy 
    xmlns:z="http://mycompany.example.com/policies" 
      env:mustUnderstand="true">
   <z:class>economy</z:class>
   <z:fareBasis>non-refundable<z:fareBasis>
   <z:exceptions>none</z:exceptions>
  </z:travelPolicy>
 </env:Header>
 <env:Body>
  <p:itinerary 
    xmlns:p="http://travelcompany.example.org/reservation/travel">
   <p:departure>
     <p:departing>New York</p:departing>
     <p:arriving>Los Angeles</p:arriving>
     <p:departureDate>2001-12-14</p:departureDate>
     <p:departureTime>late afternoon</p:departureTime>
     <p:seatPreference>aisle</p:seatPreference>
   </p:departure>
   <p:return>
     <p:departing>Los Angeles</p:departing>
     <p:arriving>New York</p:arriving>
     <p:departureDate>2001-12-20</p:departureDate>
     <p:departureTime>mid morning</p:departureTime>
     <p:seatPreference/>
   </p:return>
  </p:itinerary>
  <q:lodging 
    xmlns:q="http://travelcompany.example.org/reservation/hotels">
   <q:preference>none</q:preference>
  </q:lodging>
 </env:Body>
</env:Envelope>

5.2 他のエンコーディングスキーマを使う

SOAP Version 1.2 は特定のエンコーディングスキーマ(SOAP Part 2 section 3を参照ください)を定義していますが、その使用は任意で、仕様ではその他のエンコーディングスキーマをSOAPメッセージに含まれるアプリケーション用のデータに使ってもよいとしています。この目的のために、ヘッダブロック、SOAPのenv:Bodyの子要素、env:Detailの子要素やそれらの子孫要素を限定するxs:anyURI型のenv:encodingStyle属性を提供しています。その属性は、ネストされた内容、また少なくともそのネストされた内容の他のエンコーディングスタイルを示す他の要素で置き換えられるまで、をシリアライズするスキーマを示します。env:encodingStyle属性の値をどうするかはアプリケーション次第で、その操作結果は送り出されるデータに反映されているものと想定します。この属性が無かった場合、使われているエンコーディングについては何も示しません。

選択可能なエンコーディングスキーマの使用例を Example 17 に示します。引き続き旅行予約をテーマにして、この例では予約が確認された後に旅行サービスから旅行者に宛てた旅行詳細を示したSOAPメッセージを示しています。(同じメッセージは 他のコンテキストのExample 8bで使われています。)

Example 17:  Body要素に他のエンコーディングを使用したした例
<?xml version='1.0' ?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"> 
 <env:Header>
  <m:reservation xmlns:m="http://travelcompany.example.org/reservation" 
     env:role="http://www.w3.org/2003/05/soap-envelope/role/next"
        env:mustUnderstand="true">
   <m:reference>uuid:093a2da1-q345-739r-ba5d-pqff98fe8j7d</m:reference>
   <m:dateAndTime>2001-11-30T16:25:00.000-05:00</m:dateAndTime>
  </m:reservation>
 </env:Header>
 <env:Body>
  <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
            xmlns:x="http://travelcompany.example.org/vocab#"
    env:encodingStyle="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
   <x:ReservationRequest 
 rdf:about="http://travelcompany.example.org/reservations?code=FT35ZBQ">
      <x:passenger>Ake Jogvan Oyvind</x:passenger>
      <x:outbound>
       <x:TravelRequest>
        <x:to>LAX</x:to>
        <x:from>LGA</x:from>
        <x:date>2001-12-14</x:date>
       </x:TravelRequest>
      </x:outbound>
      <x:return>
       <x:TravelRequest>
        <x:to>JFK</x:to>
        <x:from>LAX</x:from>
        <x:date>2001-12-20</x:date>
       </x:TravelRequest>
      </x:return>
    </x:ReservationRequest>
  </rdf:RDF>
 </env:Body>
</env:Envelope>

Example 17 では、SOAPメッセージのbodyは、Resource Description Framework (RDF) [RDF]記法によるリソースグラフと属性のエンコーディングを使用した旅程記述を含んでいます。(RDF記法はこの入門書でのテーマではないので、ごく簡単に言いますと、RDFのグラフは、http://travelcompany.example.org/reservations?code=FT35ZBQにある旅行予約リソースのようなリソースと、旅行者や旅行の出発日や帰着日のような他のリソースとを各種の属性を通じて関連づけています。たとえば、旅行者用の旅行アプリケーションがRDFに対応しているカレンダーアプリケーションに格納させて複雑な方法で問合せできるように、旅程用のRDFのエンコーディングを選ぶことができます。)

 


6. SOAP 1.1 と SOAP 1.2 の違い

SOAP バージョン 1.2 ではシンタックスの変更と追加のセマンティクスがあります。以下のリストはSOAP 1.1 と SOAP 1.2 の違いを示しています。このリストでさっと違いを見てください。参照しやすいようにカテゴリに分けてますが、項目によっては別のカテゴリにもっていったほうが良いものがあるかもしれません。

ドキュメント構造

  • SOAP 1.2仕様は、2部に分かれています。[SOAP Part1] は、インフォセットをベースにしたSOAPメッセージ構造定義と下位のプロトコルバインディングフレームワークについて規定しています。[SOAP Part2] は、そのインフォセットを運ぶためにシリアライズするルールとHTTPバインディングについて規定しています。
  • SOAP 1.2 は、頭字語については説明していません。
  • SOAP 1.2 は、SOAP 1.1 で必要とされていた<?xml....?> といった形式でのシリアライズとしてではなく、XMLインフォセット用語で記述されています。

構文の追加・変更

  • SOAP 1.2 は、body要素の後にはどんな要素も許しません。SOAP 1.1 スキーマ定義では、記述上触れてはいませんが許していました。
  • SOAP 1.2 は、env:Envelope要素にenv:encodingStyle属性が無いものとしています。SOAP 1.1 では、どの要素にあっても良いものとしていました。SOAP 1.2 は、env:encodingStyle属性を使ってよい要素を規定しています。
  • SOAP 1.2 は、env:MustUnderstandフォルトコードを示すことで処理できなかった必須のヘッダブロックに載せるenv:NotUnderstoodヘッダ要素を新たに定義しています。SOAP 1.1 はフォルトコードを規定していましたが、その使用の詳細については示していませんでした。
  • SOAP 1.2 インフォセットベースの定義では、ヘッダ要素のenv:MustUnderstandは、論理値として"true" か "false"をとります。SOAP 1.1 はそれぞれリテラル値で"1" か "0"でした。
  • SOAP 1.2 は、新しいフォルトコードDataEncodingUnknownを定義しています。
  • SOAP 1.1とSOAP 1.2 では種々の名前空間が違います。
  • SOAP 1.2 では、env:actor属性をenv:role属性に変更しています。基本的に意味は同じです。
  • SOAP 1.2 では、未処理のヘッダブロックが次のノードに先送りされなくてはならないことを示すために新しいenv:actor属性を定義しています。
  • SOAP 1.2 では、2つの新しいロール"none" と "ultimateReceiver"を定義し、これらがどのように処理するかといった詳細な処理モデルを示しています。
  • SOAP 1.2 では、"dot"記法を削除して、XML修飾名を使います。名前空間プレフィックスはSOAPエンベロープ名前空間です。
  • SOAP 1.2 では、"client"と"server"フォルトコードを、"Sender"と"Receiver"に変更しました。
  • SOAP 1.2 は、env:Code と env:Reason要素名を使います。それぞれ、SOAP 1.1ではフォルトコード、フォルト文字列と呼ばれていたものです。またSOAP 1.2 では、フォルト理由を複数の言語で示すことができるようにenv:Reasonの子要素に複数のenv:Text子要素を使用できます。言語はxml:lang属性で示します。
  • SOAP 1.2 は、env:Fault要素に必須のSOAP env:Code下位要素に対して階層構造を規定していて、新たに任意のenv:Node と env:Role下位要素を追加しています。
  • SOAP 1.2 では、env:Fault要素にenv:Details要素を載せることで、SOAP 1.1にあったheaderとbodyのフォルトの差異を削除しました。SOAP 1.2 では、env:Details要素がどこにあるかということはフォルトになったSOAPメッセージのどの箇所が処理されなかったということを意味するものではありません。
  • SOAP 1.2 は、ベース(基底)URIに[XML Base]を使います。SOAP 1.1 では特に述べていません。

SOAP HTTPバインディング

  • SOAP 1.2 のHTTPバインディングでは、SOAP 1.1 で定義されていたSOAPAction HTTPヘッダが無くなりました。新しいHTTPステータスコード 427 がIANAで取得され、それを載せるせることがサーバアプリケーションによって必要とされることを示しました。
  • SOAPAction HTTPヘッダの内容は、HTTPバインディングにあらわれる"application/soap+xml"メディアタイプの(任意の)"action"パラメタの値として示されます。
  • SOAP 1.2 のHTTPバインディングでは、Content-typeヘッダは、SOAP 1.1にある"text/xml"ではなく"application/soap+xml"とします。 この新しいメディアタイプのIETFへの登録は保留されています。
  • SOAP 1.2 は、2xx, 3xx, 4xx の色々なHTTPステータスコードの使用についてよりきめ細かく説明しています。
  • HTTP拡張フレームワークのサポートは、SOAP 1.2から削除されました。
  • SOAP 1.2 は、安全でべき等な情報の取得をするためのHTTP GETを使用できるHTTPバインディングのひとつとしてメッセージパターンを追加しています。

RPC

  • SOAP 1.2 は、RPCのためにrpc:result要素アクセサを提供しています。
  • SOAP 1.2 は、RPC名前空間にいくつかのフォルトコードを追加しています。
  • SOAP 1.2 は、プロシジャの目的が安全な情報取得のときのRPCを定義するために、Webと親和性のあるアプローチについてガイダンスを提供しています。

RPC

  • SOAP 1.2 は、RPCのためにrpc:result要素アクセサを提供しています。
  • SOAP 1.2 は、RPC名前空間にいくつかのフォルトコードを追加しています。
  • SOAP 1.2 は、プロシジャの目的が安全な情報取得のときのRPCを定義するために、Webと親和性のあるアプローチについてガイダンスを提供しています。

SOAPエンコーディング

  • SOAP 1.2では、有効辺ラベル付きグラフに基づいた抽象データモデルが明確に定義されました。
  • SOAP 1.2 のエンコーディングは、このモデルに依存しています。SOAP RPC規約はこのデータモデルに依存しますが、SOAPエンコーディングには依存しません。SOAP 1.2 エンコーディングとSOAP 1.2 RPC規約のサポートは任意です。
  • SOAP 1.2では、配列をシリアライズするための構文がSOAP 1.1から変更されました。
  • SOAP 1.1 で提供されていた部分転送と分散配列のサポートは、SOAP 1.2では利用できません。
  • SOAP 1.2では、多重参照値のインライン・シリアライズが可能です。
  • SOAP 1.1 のxs:anyURI型のhref属性は、SOAP 1.2 ではIDREF型のenc:refとします。
  • SOAP 1.2では、省略された複合型のアクセサは、NILと同値となります。
  • SOAP 1.2は、エンコーディングエラーを示すためにいくつかのフォルト・サブコードを提供します。
  • SOAP 1.2では、ノードのタイプはオプションになりました。
  • SOAP 1.2は、SOAPデータモデルから汎用の複合型を削除しました。
  • SOAP 1.2は、SOAPエンコーディングを使用して符号化された要素に対して、その構造(たとえば、単純な値、構造、配列とか)を識別するための任意属性enc:nodeTypeを追加しました。

 

SOAP Part 1 Appendix Aは、[SOAP 1.1]からSOAP Version 1.2 へのバージョン移行をサポートするためのSOAPノードのバージョンマネージメントルールを提供しています。特に、[SOAP 1.1] メッセージを受信したSOAP 1.2 のノードが、それがサポートしているSOAPのバージョンをメッセージの生成者に通知するために、SOAPフォルトメッセージを送るために使うことができるenv:Upgrade ヘッダブロックの定義で示しています。

 


7. 参照資料

 

[SOAP Part1] W3C Recommendation "SOAP 1.2 Part 1: Messaging Framework", Martin Gudgin, Marc Hadley, Jean-Jacques Moreau, Henrik Frystyk Nielsen, 24 June 2003 (See http://www.w3.org/TR/2003/REC-soap12-part1-20030624/.)

[SOAP Part2] W3C Recommendation "SOAP 1.2 Part 2: Adjuncts", Martin Gudgin, Marc Hadley, Jean-Jacques Moreau, Henrik Frystyk Nielsen, 24 June 2003 (See http://www.w3.org/TR/2003/REC-soap12-part2-20030624.)

[RFC 2396] IETF "RFC 2396: Uniform Resource Identifiers (URI): Generic Syntax", T. Berners-Lee, R. Fielding, L. Masinter, August 1998. (See http://www.ietf.org/rfc/rfc2396.txt.)

[HTTP 1.1] IETF "RFC 2616: Hypertext Transfer Protocol -- HTTP/1.1", R. Fielding, J. Gettys, J. C. Mogul, H. Frystyk, T. Berners-Lee, January 1997. (See http://www.ietf.org/rfc/rfc2616.txt.)

[XML 1.0] W3C Recommendation "Extensible Markup Language (XML) 1.0 (Second Edition)", Tim Bray, Jean Paoli, C. M. Sperberg-McQueen, Eve Maler, 6 October 2000. (See http://www.w3.org/TR/2000/REC-xml-20001006.

[Namespaces in XML] W3C Recommendation "Namespaces in XML", Tim Bray, Dave Hollander, Andrew Layman, 14 January 1999. (See http://www.w3.org/TR/1999/REC-xml-names-19990114/.)

[XML Schema Part1] W3C Recommendation "XML Schema Part 1: Structures", Henry S. Thompson, David Beech, Murray Maloney, Noah Mendelsohn, 2 May 2001. (See http://www.w3.org/TR/2001/REC-xmlschema-1-20010502/ )

[XML Schema Part2] W3C Recommendation "XML Schema Part 2: Datatypes", Paul V. Biron, Ashok Malhotra, 2 May 2001. (See http://www.w3.org/TR/2001/REC-xmlschema-2-20010502/ )

[SMTP] SMTPは一連のRFCで定義されています:

[RDF] W3C Recommendation "Resource Description Framework (RDF) Model and Syntax Specification", O. Lassila and R. Swick, Editors. World Wide Web Consortium. 22 February 1999. (See http://www.w3.org/TR/REC-rdf-syntax.)

[SOAP 1.1] W3C Note "Simple Object Access Protocol (SOAP) 1.1", Don Box et al., 8 May, 2000 (See http://www.w3.org/TR/SOAP/)

[XML Infoset] W3C Recommendation "XML Information Set", John Cowan, Richard Tobin, 24 October 2001. (See http://www.w3.org/TR/xml-infoset/)

[SOAP MediaType] IETF Internet Draft "The 'application/soap+xml' media type", M. Baker, M. Nottingham, "draft-baker-soap-media-reg-03.txt", May 29, 2003. (See http://www.ietf.org/internet-drafts/draft-baker-soap-media-reg-03.txt, note that this Internet Draft expires in November 2003)

[SOAP Email Binding] W3C Note "SOAP Version 1.2 Email Binding", Highland Mary Mountain et al, draft June 13, 2002. (See http://www.w3.org/TR/2002/NOTE-soap12-email-20020626.)

[XML Base] W3C Recommendation "XML Base", Jonathan Marsh, 27 June 2001. (See http://www.w3.org/TR/2001/REC-xmlbase-20010627/)

[RFC 2119] IETF "RFC 2119: Key words for use in RFCs to Indicate Requirement Levels", S. Bradner, March 1997. (See http://www.ietf.org/rfc/rfc2119.txt.)

 


A. 謝辞

(翻訳は)省略させていただきます。


[たのしいXML のインデックス]へ