このシリーズのパート 1 では、クロスブラウザー対応の JavaScript ライブラリーの例を紹介し、RPC エンコード形式およびドキュメント・リテラル形式の要求ができる単純な SOAP Web サービス・クライアントを用意しました。このクライアントには、要求および応答ハンドラー、カスタム XML シリアライザー/デシリアライザー、およびSOAP ヘッダーがインクルードされています。今回の WS-Addressing および WS-ResourceFramework の実装では、これらの要素すべてを利用します。
ws.js (パート 1 参照) には、次のような基本オブジェクトが定義されています。
- WS.Call: XMLHttpRequest をラップする Web サービス・クライアント
- WS.QName: XML 修飾名の実装
- WS.Binder: カスタム XML シリアライザー/デシリアライザーの基本
- WS.Handler: 要求/応答ハンドラーの基本
- SOAP.Element: XML DOM をラップする基本 SOAP 要素
- SOAP.Envelope: SOAP.Element を拡張する SOAP エンベロープ・オブジェクト
- SOAP.Header: SOAP.Element を拡張する SOAP ヘッダー・オブジェクト
- SOAP.Body: SOAP.Element を拡張する SOAP ボディ・オブジェクト
- XML: XML を処理するための、クロスプラットフォームのユーティリティー・メソッド
これらのオブジェクトのうち、WS.QName、SOAP.Element、WS.Handler、WS.Binder、WS.Call、の 5 つは、WS-Addressing および WS-ResourceFramework の実装ではきわめて重要ですので、このシリーズのパート 1 に戻って各オブジェクトの基本的な機能をぜひもう一度ご確認ください。
このパート 2 では、新たに 2 つの JavaScript ファイルについて説明します。1 つは、WS-Addressing をサポートするオブジェクトの定義ファイル (wsa.js)、そしてもう 1 つは、WS-ResourceFramework の基本実装をサポートするオブジェクトの定義ファイル (wsrf.js) です。
図 1. Web サービス JavaScript ライブラリーを使用した、Web ブラウザーからの Web Service Resource Framework サービスの呼び出し
wsa.js には次のような基本オブジェクトを定義します。
- WSA.EndpointReference: WS-Addressing EndpointReference オブジェクト
- WSA.EndpointReference.ReferenceParameters: WS-Addressing EndpointReference 参照パラメーター用のコンテナー
- WSA.EndpointReference.Binder: WSA.EndpointReference オブジェクトの XML シリアライザー/デシリアライザー
- WSA.MessageContext: WS-Addressing SOAP メッセージ・ヘッダーのメタデータ用コンテナー
- WSA.Handler: WS-Addressing SOAP メッセージ・ヘッダーを SOAP エンベロープ内に挿入する要求ハンドラー
wsrf.js には次のような基本オブジェクトを定義します。
- WSRF.Request.GetResourceProperty: WS-ResourceFramework の GetResourceProperty 操作のラッパー
- WSRF.Request.GetMultipleResourceProperties: WS-ResourceFramework の GetMultipleresourceProperties 操作のラッパー
- WSRF.Resource: WS-ResourceFramework 操作を呼び出すためのクライアント・インターフェース
今回は、新しく習得しなければならない JavaScript オブジェクトの数がかなり多いと感じるかもしれません。しかし、これらのオブジェクトによって提供される API は、実際に Web サービスを呼び出すためのプログラミング作業が最小限で済むように設計されています。たとえば、後半で説明するリスト 8 を見てください。この API では、WS-ResourceFramework 仕様に準拠した Web サービスに対するメソッドを、わずか数行のコードで呼び出すことができます。つまり、基礎となる SOAP 実装の細部に手間を取られる必要がないという点が強みです。
Web Services Addressing 仕様には、アドレッシング情報を SOAP エンベロープに挿入するための仕組みが定義されています。WS-Addressing の中枢を担うのは EndpointReference と呼ばれるオブジェクトで、特定の Web サービス・インスタンスへの参照や記述の役目を果たします (リスト 1 を参照)。また、Web Services Addressing 仕様で EndpointReference の次に定義されているのは、アドレッシング情報を SOAP エンベロープ内に直接渡すために使用する、数種の SOAP メッセージ・ヘッダーです。
JavaScript ライブラリー wsa.js では、WS-Addressing EndpointReference および SOAP メッセージ・ヘッダー要素の基本的なサポートを実装する複数のオブジェクトが提供されます。
リスト 1.単純な WS-Addressing EndpointReference
<EndpointReference xmlns="http://www.w3.org/2005/08/addressing">
<Address>http://www.example.org/services/HelloWorld</Address>
<ReferenceParameters>
<abc:foo xmlns:abc="urn:foo">This is a test</abc:foo>
</ReferenceParameters>
</EndpointReference>
|
WSA.EndpointReference オブジェクトは、リスト 2 に示したとおり、WS-Addressing EndpointReferences を指定するために使用します。このコードを上記の XML コードと比べてみると、WSA.EndpointReference の API の働きがよく分かるはずです。
リスト 2. wsa. js による EndpointReference の作成
var epr =
new WSA.EndpointReference(
"http://www.example.org/services/HelloWorld");
var epr_rp = epr.create_reference_parameters();
epr_rp.create_child(
new WS.QName('foo','urn:foo','abc')).
set_value('This is a test');
|
WSA.EndpointReference の API は現在、WS-Addressing 情報モデルで定義されている Address および ReferenceParameters プロパティーをサポートしています。Metadata プロパティーは、今回実装するクライアントの基本機能には重要でないため、実装されていません。
WS-Addressing SOAP メッセージ・ヘッダーは、Web サービス・クライアントからサービスに対して送信される SOAP エンベロープに設定されることを前提としています。JavaScript ライブラリー ws.js に定義した WS.Call オブジェクトでは、基礎となる SOAP.Envelope との連携の詳細が隠蔽されるので、適切なヘッダーを挿入するには WS.Handler を使用する必要があります。
Web サービス・クライアントは、個々の要求、応答、エラーごとに WS.Handler オブジェクトのメソッドを呼び出します。WS-Addressing の実装のために用意されている WSA.Handler は、メッセージに挿入する必要のある情報を含んだ対応する WSA.MessageContext オブジェクトを使用します (リスト 3 を参照)。
リスト 3.WS-Addressing のコンテキストとハンドラーの使用
var address = 'http://www.example.com/services/HelloWorld';
var ctx = new WSA.MessageContext();
ctx.to = new WSA.EndpointReference(address);
ctx.replyto = new WSA.EndpointReference(WSA.ANONYMOUS);
ctx.action = address + '#SayHello'
var handler = new WSA.Handler();
handler.set_context(ctx);
var call = new WS.Call('');
call.add_handler(handler);
|
個々の WS-Addressing SOAP メッセージ・ヘッダーに対応する WSA.MessageContext オブジェクトのプロパティーは次のとおりです。
- to: WSA.EndpointReference オブジェクトを指定し、その Address プロパティーにはメッセージの宛先を示す絶対 URI を指定します。
- from: メッセージの送信元を示す WSA.EndpointReference オブジェクトを指定します。
- replyto: 応答の送信先を示す WSA.EndpointReference オブジェクトを指定します。
- faultto: 障害メッセージの送信先を示す WSA.EndpointReference オブジェクトを指定します。
- action: そのメッセージによってトリガーされるアクションを示す絶対 URI を指定します。
- messageid: メッセージを一意に識別する絶対 URI を指定します。
- relatesto: 関係するメッセージを示す URI の対の配列を指定します。この対のうち、関係するメッセージの関係タイプを示す URI は 1 番目に、固有のメッセージ ID を示す URI は 2 番目に指定します。
WSA.Handler が Web サービスを呼び出すための WS.Call オブジェクトに登録されると、その WS.Call オブジェクトは個々の要求ごとにハンドラーを呼び出して SOAP.Envelope オブジェクトへの参照をハンドラーに渡します。ハンドラーは WSA.MessageContext から情報をプルし、リスト 5 のように適切なヘッダーをメッセージに追加します。
Web Services Resource Framework 仕様には、ステートフル・リソースのインスタンスに対するアクセスと操作を行うための Web サービス標準の使用規則が定義されています。各リソースの識別と参照は WS-Addressing EndpointReferences によって行います。リソースの各種プロパティーを取得または変更する目的で、少数の共通操作を使用する場合もあります。
JavaScript ライブラリー wsrf.js は、GetResourceProperty およびGetMultipleResourceProperties 操作をサポートすることにより、Web Services Resource Framework の部分的な実装を提供します。wsrf.js の API は ws.js および wsa.js の両 API を基盤として構築され、包括的な WS-ResourceFramework の実装を提供することよりも、これら 2 つのスクリプトの用途を明確に示すことを目的として設計されています。
WS-ResourceFramework における操作は、特定のリソース・インスタンスに向けて送信されるドキュメント・リテラル形式の SOAP 要求です。ターゲット・リソースは、リスト 4 のように WS-Addressing EndpointReference によって指定します。
リスト 4.WSRF EndpointReference の記述例
<EndpointReference xmlns="http://www.w3.org/2005/08/addressing">
<Address>http://localhost:9080/SoapAjax2/services/DeviceService</Address>
<ReferenceParameters>
<abc:DeviceID xmlns:abc="urn:deviceservice">ABC123</abc:DeviceID>
</ReferenceParameters>
</EndpointReference>
|
wsa.js に定義した仕組みを使用して、WSRF EndpointReference に含める情報を SOAP エンベロープ内に記述する場合、その情報は SOAP メッセージ・ヘッダーの形式で記述する必要があります (リスト 5 を参照)。
リスト 5.WSRF GetResourceProperty 要求の記述例
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
<Header>
<To xmlns="http://www.w3.org/2005/08/addressing">
http://localhost:9080/SoapAjax2/services/DeviceService</To>
<abc:DeviceID xmlns="urn:deviceservice">ABC123</abc:DeviceID>
</Header>
<Body>
<GetResourceProperty
xmlns="http://docs.oasis-open.org/wsrf/rp-2"
xmlns:ns="urn:foo">ns:bar</GetResourceProperty>
</Body>
</Envelope>
|
wsrf.js によって提供される API は、SOAP エンベロープおよび WS-Addressing ヘッダー (いずれも WS-ResourceFramework の Web サービス間の相互作用を可能にするために必要な要素) との連携の詳細を隠蔽するように設計されています。ただし、コードを一読すれば、そのコードの機能に関する重要な特性をいくつも確認できます。
リスト 6 は、WSRF GetResourceProperty 操作のラッパー・オブジェクトの記述例です。このラッパーは wsrf. js ライブラリーによって内部的に使用されるもので、SOAP エンベロープの作成およびこの操作に不可欠な XML コードの構築時に必要となる基本的メカニズムがラッパー内に含まれています。このラッパー・オブジェクトでは、ws.js によって提供される SOAP.Element API と SOAP.Envelope API が利用されている点に注目してください。このラッパー・オブジェクトの初期化の際に渡される「qname」パラメーターは、要求されているプロパティーの XML 修飾名です。
リスト 6.WSRF GetResourceProperty 要求ラッパー
WSRF.Request.GetResourceProperty = Class.create();
WSRF.Request.GetResourceProperty.prototype = {
initialize : function(qname) {
this.envelope = new SOAP.Envelope();
this.set_qname(qname);
},
set_qname : function(qname) {
var body = this.envelope.create_body();
var method = body.create_child(
WSRF.Request.QNAME_GETRESOURCEPROPERTY);
if (!qname.namespace) qname.namespace = '';
if (!qname.prefix) qname.prefix = 'ns';
method.declare_namespace(qname);
method.set_value(qname.value_of());
}
};
|
リスト 7 は、WSRF. Resource オブジェクトからのコード・スニペットです。ご覧のように、WS.Call オブジェクトを作成し、適切な SOAP メッセージ・ヘッダー設定のために使用する WSA.Handler オブジェクトを準備し、WSRF.Request.GetResourceProperty ラッパー・オブジェクトを作成し、Web サービス操作を呼び出しています。
リスト 7.WSRF GetResourceProperty の呼び出し
get_resource_property : function(qname, callback) {
var call = new WS.Call(this.address);
var handler = new WSA.Handler();
var wsactx = new WSA.MessageContext(this.epr);
handler.set_context(wsactx);
call.add_handler(handler);
var req = new WSRF.Request.GetResourceProperty(qname);
call.invoke(req.envelope, callback);
}
|
アプリケーションが WS-ResourceFramework の Web サービスに対して GetResourceProperty 操作を呼び出すには、ターゲットの WS-Resource の EndpointReference を提供し、取得するプロパティー識別のための WS.QName オブジェクトを提供するだけで済みます (リスト 8 を参照)。
リスト 8.一括プル
var ADDRESS = 'http://localhost:9080/SoapAjax2/services/DeviceService'
function getDeviceName(deviceID, container) {
var epr = new WSA.EndpointReference(ADDRESS);
var epr_rp = epr.create_reference_parameters();
epr_rp.create_child(
new WS.QName(
'DeviceID',
'urn:deviceservice')).set_value(deviceID);
var res = new WSRF.Resource(ADDRESS, epr);
res.get_resource_property(
new WS.QName('DeviceName','urn:deviceservice'),
function(call,envelope) {
$('soap').innerHTML = arguments[2].escapeHTML();
}
);
}
|
リスト 8 では、WS-Resource に対する呼び出しを、HTML ページのどこからでも呼び出せる都合のよい関数でラップしています。リスト 9 では、id という入力フィールドから device id に入り、result というデバイス要素に SOAP 応答エンベロープを出力するボタンを提供します。
リスト 9. getDeviceName の呼び出し
<input
value="Invoke the Web Service"
type="button"
onclick="getDeviceName($('id').value,$('result'))" />
|
今回は、このシリーズのパート 1 で紹介した Ajax Web サービス・クライアントを拡張することによって、Web Services Addressing や Web Services Resource Framework といった高度な Web サービス標準技術をサポートする方法について説明しました。次回は Web サービス記述言語 (WSDL) のサポートについて詳しく解説します。
| 内容 | ファイル名 | サイズ | ダウンロード形式 |
|---|---|---|---|
| Sample project | ws-wsajax2code.zip | 14KB | HTTP |
学ぶために
- Ajax による SOAP Web サービスの呼び出し ? このシリーズの全パートをお読みください。
- Build dynamic Java applications -- Philip McCarthy による Java 開発者のための Ajax 解説です (developerWorks、2005年9月)。
- XMLHttpRequest API -- XMLHttpRequest の API について詳しく学べる、XUL Planet の Web サイトです。
- Mozilla Web Services -- Mozilla/Firefox の組み込み Web サービス・サポートについて詳しく学びましょう。
- Web Services Resource Framework ? OASIS の Web Services Resource Framework 仕様に関する活動について詳しく学びましょう。
- Web Services Addressing -- W3C の Web Services Addressing 仕様に関する活動について詳しく学びましょう。
- Standards roadmap -- SOA および Web サービスの開発に関する標準や仕様の影響と重要性について理解してください。
- Architecture: Build for the future -- 「developerWorks」の「Architecture」エリアから、アーキテクチャーの構築スキルを高めるために必要な情報や資料を入手できます。
- SOA and web services -- Web サービス・アプリケーションの開発手法に関する数々の有益な記事や、入門レベル、中級レベル、および上級レベルのチュートリアルが用意されています。
議論するために
- developerWorks blogs から、developerWorks コミュニティーに参加してください。
James Snellは、IBMのEmerging Technologies Toolkitチームの一員です。過去2年間は、新興のWebサービス技術や標準などに焦点を当てており、またAtom 1.0仕様にも貢献しました。新興技術に焦点を当てた ウェブログ を維持管理しています。