Dojo を使って Web サービスのレスポンスを処理する

Web サービスの使い方を Dojo で単純化する

Web サービスを使用すると、言語やプラットフォームに依存しない形で機能を公開することができます。クライアント・サイドでは、最小限のプログラミングでリッチなクライアント・エクスペリエンスを提供するための JavaScript ツールとして、Dojo の人気が高まりつつあります。皆さんがこれまで使ってきた Dojo を活用し、Web サービスのレスポンスを解析、処理する方法を学びましょう。

Brian M. Carey, Senior Systems Engineer, Triangle Information Solutions

Brian Carey は情報システムのコンサルタントであり、Java、Java Enterprise、PHP、Ajax、そしてそれらの関連技術を専門としています。Twitter で Brian Carey をフォローするためには http://twitter.com/brianmcarey にアクセスしてください。



2010年 7月 27日

Web サービスとは何か

Web サービスは、HTTP (Hypertext Transfer Protocol) を使ってアクセスされる Web ベースの API (Application Programming Interface ) です。ホスト・サイドでは、WSDL (Web Services Description Language) と呼ばれる XML (Extensible Markup Language) を使って特定の操作が定義されます。クライアントとホストとの間での情報交換のための仕様は SOAP (Simple Object Access Protocol) と呼ばれています。Web サービスはまさに頭字語の世界です。

現実的な観点で見ると、Web サービスによって情報交換のための集中アクセス・ポイントを実現することができます。名前からもわかるように、Web サービスは世界中のクライアントにサービスを提供します。例えば Web サービスを利用すると、最新のニュース見出しやオンライン書店での新刊リスト、あるいは特定の地域の釣りレポートの履歴などを入手することができます。同じく Web サービスという名前が示すように、こうした情報は多くの場合、報道機関の Web サイトや個人のブログなどに掲載されます。

Dojo とは何か

Dojo は JavaScript で開発するための、オープンソースの UI (User Interface) ツールキットであり、Dojo を利用することで JavaScript アプリケーションを迅速にデプロイすることができます。Dojo は、JavaScript コードの作成に要する時間を短縮し、複雑さを軽減するための一連の JavaScript ライブラリーと考えることができます。

Dojo フレームワークの主要コンポーネントの 1 つに、Dojo Base と呼ばれるコンポーネントがあります。Dojo ライブラリーに含まれる Dojo Base では、イベント処理、Ajax (Asynchronous JavaScript + XML) 呼び出し、CSS (Cascading Style Sheets) クエリー、さまざまなエフェクト、などの難解な部分の処理を行います。

Dojo Base の他には、Dojo の中で最もよく使われる機能の 1 つである、Dijit と呼ばれるウィジェットがあります。Dijit は再利用可能な一連のクライアント・サイド・コンポーネントであり、実際に皆さんが作成するアプリケーションの中にドラッグ・アンド・ドロップすることができます。アプリケーションのルック・アンド・フィールをカスタマイズするためには、こうしたウィジェットのほとんどで構成の簡単な変更を 2、3 行えばよいのです。

Web サービスを利用するアプリケーションを、Dojo を使って作成する

FishinHole.com の取締役会は、自社のカタログを Web サービスを使って公開する (そして検索可能にする) ことを決定しました。そうすることで自社の製品を Web 全体に広く拡販することができ、競争力も増すと考えたのです。取締役会はあなたに対し、Web サービスとそのプロトタイプを作成するように依頼しました。プロトタイプでは、その Web サービスへのアクセス方法を非常に単純な Web ページを使って説明できなければなりません。この仕事の期限は明日です。

FishinHole.com は自社のオンライン・カタログで既に PHP を使用しているため、Web サービスにも PHP を使うのが妥当です。NuSOAP という PHP ライブラリーを使用すると、PHP による Web サービス・アプリケーションの開発をより迅速に行えるようになるのに加え、SOAP 1.1 仕様の大部分がサポートされ、WSDL 1.1 に準拠した文書を生成するのも可能になります。

ここで、クライアントのニーズについて考えてみると、この Web サービスは「非常に単純なもの」でなければなりません。そのためには、この Web サービスはローカルのパーソナル・コンピューター上で実行することができ、PHP による変換プログラム (またはその他の変換プログラム) を必要としないものでなければなりません。多少の JavaScript コードを含む単純な HTML ページであれば、望んだ結果を得ることができます。最初に作成されるものは非常に単純なものですが、それを Dojo によって拡張することができ、凝ったユーザー・インターフェース機能を後から追加することができます。いずれにせよ Dojo を使用するので、一貫性の点から、XML の処理にも Dojo を使用することにします。

単純な Web サービスをデプロイする

ここで NuSOAP を使って PHP でコーディングする Web サービスでは、FishinHole.com が販売する釣り用のルアーのリストを、ルアーのタイプに基づいて返します。この例は非常に簡単で、ルアーのタイプは trolling (トローリング)、casting (キャスティング)、other (その他) という 3 つしかありません。

リスト 1 を見ると、PHP と NuSOAP を使ってSOAP 準拠の Web サービスを作成することがいかに簡単であるかがわかります。

リスト 1. PHP による単純な Web サービス
<?php
require_once('nusoap.php');
$server = new soap_server;
$server->register('retrieveByType');

function retrieveByType($type) {
    if ($type == 'trolling') {
        $arr[0] = 'Donzai Deep Swimmer 5 1/4 inch';
        $arr[1] = 'Yosubi Squid-like 4 inch';
        $arr[2] = 'Fortunata Imperial High Action';
    } else if ($type == 'casting') {
        $arr[0] = 'Silver Spring Mirrors Size 00';
        $arr[1] = 'Gold Spring Mirrors Size 0';
        $arr[2] = 'Mini Minnow Blue';
    } else {
        $arr[0] = 'None found!';
    }

    return $arr;
}

$HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA) ? $HTTP_RAW_POST_DATA : '';
$server->service($HTTP_RAW_POST_DATA);
?>

最初の行 (require_once の行) は必要な NuSOAP ライブラリーを参照しています。NuSOAP ライブラリーを利用するためには、まず NuSOAP ライブラリーをダウンロードする必要があります。NuSOAP のダウンロードについて詳しくは「参考文献」を参照してください。

次に、$server という PHP オブジェクトをインスタンス化しています。このオブジェクトは soap_server 型であり、この型は NuSOAP PHP ライブラリーの中で定義されています。クライアントが Web サービスの操作の 1 つを呼び出すと、この $server オブジェクトを使ってその操作の処理が行われ、その結果が返されます。

その次の行では、Web サービスの操作として関数を登録しています。この例では 1 つの操作しかないため、関数は 1 つしかありません。また、この例をわかりやすいものにするため、操作の名前と関数の名前は同じにしてあります (この例に限らず、操作名と関数名を同じにしておくことは、混乱を回避できるため、適切なプラクティスです)。retrieveByType という SOAP 操作を呼び出すと、同じ retrieveByType という名前の PHP 関数が呼び出されます。

次に、この PHP 関数のコードを記述しています。この関数が type という 1 つの引数を取ることに注意してください。この typetrolling (トローリング) または casting (キャスティング) という 2 つのストリングに対して評価します。type パラメーターと 2 つのストリングのいずれか 1 つが一致すると、該当するルアーの配列が返されます。どちらにも一致しない場合には、None found! (見つかりません!) というストリングが返されます。

最後から 2 番目の行は、この Web サービスが操作の呼び出しをどう処理するかを記述しています。リストを見るとわかるように、この Web サービスは、操作の呼び出しが (GET ではなく) POST リクエストによって行われるものと想定しています。これは Web アプリケーションでフォームの送信を処理する通常の方法と似ています。またこの行ではヌル値をトラップして空のストリングに変換し、この後の処理で問題が発生しないようにしています。

最後に、サーバー・オブジェクトがオブジェクト自身の service 関数を呼び出しています。この関数は POST されたデータを受け付け、そのデータに対して適切なレスポンスをクライアントに返します。

これで Web サービスが完成しました。このファイルに webservice.php という名前を付け、適当なホスト上に配置します。

JavaScript コードを使ってサービスを呼び出す

新しい Web サービスから返される XML の処理と構文解析に Dojo を使用しているため、クライアント・コードの先頭で Dojo ライブラリーを参照する必要があります (リスト 2)。

リスト 2. Dojo ライブラリーを参照する
<script src="http://ajax.googleapis.com/ajax/libs/dojo/1.4/dojo/dojo.xd.js" 
	type="text/javascript"></script>

上記のコードが HTML ページの head 要素の中に入ります。このように Dojo を参照することで、ライブラリーをダウンロードする必要がなくなります。参照されるライブラリーは Web 上のどこかに既に存在しているからです。しかし残念ながら、その参照された Web サイトがダウンすると、アプリケーションもダウンしてしまいます。幸い、そうしたことが Google で起こるとは考えられません。

リスト 3 は、この Web サービスを HTML ページからプログラムで呼び出す方法を示しています。

リスト 3. invokeService() 関数
function invokeService(type) {
    soapMessage = '<?xml version="1.0" encoding="ISO-8859-1"?>';
    soapMessage+='<SOAP-ENV:Envelope SOAP-ENV:";
    soapMessage+=;encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"';
    soapMessage+=' xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"';
    soapMessage+=' xmlns:xsd="http://www.w3.org/2001/XMLSchema"';
    soapMessage+=' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"';
    soapMessage+=' xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"';
    soapMessage+=' xmlns:si="http://soapinterop.org/xsd">';
    soapMessage+=' <SOAP-ENV:Body> <ns1:retrieveByType ';
    soapMessage+='xmlns:ns1="http://fishinhole.com">';
    soapMessage+=' <type xsi:type="xsd:string">' + type + '</type>';
    soapMessage+=' </ns1:retrieveByType> </SOAP-ENV:Body> </SOAP-ENV:Envelope>';
   
    if(window.XMLHttpRequest) {
            httpRequest=new XMLHttpRequest();
	} else if (window.ActiveXObject) { 
            httpRequest=new ActiveXObject("Microsoft.XMLHTTP"); 
    }
                  
    httpRequest.open("POST",url,true);
    if (httpRequest.overrideMimeType) { 
            httpRequest.overrideMimeType("text/xml"); 
    }
    httpRequest.onreadystatechange=populateDiv;
      
    httpRequest.setRequestHeader("Man", url + " HTTP/1.1")
    httpRequest.setRequestHeader("MessageType", "CALL");
    httpRequest.setRequestHeader("Content-Type", "text/xml");

    httpRequest.send(soapMessage);
    valTimeout=setTimeout("timeout(httpRequest);",120000);              
}

大量のコードがあるように見えるかもしれませんが、このリストの内容は Ajax を理解している開発者にとっては非常に単純です。

まず、SOAP 準拠のメッセージがストリングとして作成されています。メッセージの大部分はハードコーディングされていますが、ルアーのタイプは例外で、trolling (トローリング)、casting (キャスティング)、other (その他) という 3 つのストリングのいずれかになります。これらのタイプは見慣れたもののはずですが、other (その他) は例外かもしれません (other (その他) は結果が None found! (見つかりません!) の場合をテストするために用意されています)。

SOAP メッセージを作成した後、数行のコードを追加してブラウザーの違いに対応しています。クライアントで使用されているブラウザーの種類を基に、ブラウザーに応じた HTTP リクエスト・オブジェクトをインスタンス化します。このオブジェクトには httpRequest という名前が付けられています。

Web サービスへのアクセスには POST メソッドを使っています。このことは httpRequestopen 関数を実行している行を見れば明らかです。先ほどのコーディングでは、この動作を想定していました。この Web サービスをどこにデプロイするかによって、この関数への入力パラメーターである url が決まります (url は http://www.myhost.com/webservice.php のような形式をしています)。

httpRequest オブジェクトの onreadystatechange 関数を呼び出す動作は、このページの機能としては特に重要です。onreadystatechange 関数は populateDiv に設定されていますが、populateDiv は Web サービスが応答する際にコールバックとして動作する JavaScript 関数の名前です。

次の数行のコードでは特定のヘッダー情報を設定しています。それが終わると、send メソッドが呼び出された時にこの Web サービスが正式に呼び出されます。この関数のパラメーター入力が先ほど作成した SOAP メッセージであることに注意してください。

リスト 4 は JavaScript 関数の populateDiv を示しています。

リスト 4. populateDiv 関数
function populateDiv(){
   	try {
       if(httpRequest.readyState==4) {
            if(httpRequest.status==200) {
            clearTimeout(valTimeout);
          var text = httpRequest.responseText;
          var dom = dojox.xml.parser.parse(text); 
          var docNode = dom.documentElement; 
          var html = "";

          var returnElement = docNode.childNodes[0].childNodes[0].childNodes[0];

          for (var i = 0; i < returnElement.childNodes.length; i++) { 
           html +="<br/>" + 
        	dojox.xml.parser.textContent(returnElement.childNodes[i]);
          }

          var resultDiv=document.getElementById("resultDiv");
          resultDiv.innerHTML = html;
         	}
        } 
   	 } catch(e) { 
       alert("Error!"+e.description); 
     }      
}

リクエスト/レスポンス・メカニズムと XML の構文解析の両方を扱っているため、この関数全体が try/catch ブロックで囲まれていることに注意してください。おそらく、発生する例外をすべてトラップし、デバッグ用に出力する必要があるでしょう。

ここでは、いくつかのチェックが行われています。レスポンスを受信すると、リクエスト・オブジェクトは 4 という readyState を登録します。レスポンスが有効な場合には、リクエスト・オブジェクトは 200 というステータスを登録します。

有効なレスポンスを受信すると、タイムアウト変数がクリアされます。これはつまり、Web サービスのタイムアウトを気にする必要がないということです。

次に、実際のレスポンスのテキストを取得します (レスポンスは XML フォーマットであり、先ほどコーディングしたレスポンスと驚くほど似ているはずです)。このレスポンスには、選択されたルアーのタイプに応じたレスポンスとしてのテキストを含む要素が含まれています。

最後に、Dojo を呼び出すことで、返された XML の SOAP メッセージを構文解析し、次のコード行で、そのメッセージのルート要素を操作できるようにします。

ここで、NuSOAP Web サービスによって返された 1 つまたは複数の item 要素を探します。これらの要素はレスポンスの奥深く 4 階層目に埋もれています (そのため、returnElement オブジェクトを設定する行があります)。これは別の見方をすれば、ルート要素のひ孫の子を探していることになります。これらの要素を取得するためには、ひ孫の子それぞれに対して繰り返し処理を行います (この要素は return という名前であり、それが JavaScript オブジェクト returnElement の名前の元になっています)。

これら、ひ孫の子それぞれに対して繰り返し処理を行った後、その要素のテキスト部分 (この場合はルアーの説明) のみを抽出し、このテキスト部分の前に <br/> タグを追加し、各ルアーの名前を改行で区切ります。

最後に、DIV 要素を取得し、この DIV 要素を使ってレスポンスを表示します。すると生成された HTML がその DIV の中に配置され、瞬時に表示されます。

テスト

クライアント・コードと Web サービスのコードを用意できたら、このプロトタイプをテストします。

クライアントは単純にローカルのコンピューター上で実行されます。どのような Web ブラウザーでも (Microsoft® Windows® の Internet Explorer や Mozilla Firefox など)、ローカルの HTML ファイルを処理することができ、それは HTML ファイルに JavaScript コードが使われている場合も同じです。

Web ページが表示されると、そのページに単純なドロップダウン・メニューが表示され、そのメニューからルアーのタイプを選択することができます。「Trolling (トローリング)」を選択し、しばらく待つと、その結果がドロップダウン・メニューの下に表示されます。「Casting (キャスティング)」を選択すると、表示される結果が変わります。「Other (その他)」を選択すると、「None found! (見つかりません!)」が表示されます。

まとめ

あなたが出した成果は、取締役会で非常に好印象を得られました。あなたは締め切りに間に合わせることができ、しかも「非常に単純な」Web サービスを作成することができました。

もっと重要な点として、PHP、NuSOAP、Dojo という、使い勝手のよい技術をうまく使うための方法を示すことができました。その過程で、皆さんは自分が持つ優れた能力を示すとともに、アプリケーションの統合がいかに短時間で効率的に行えるものかを示しました。最後に、このソリューションによって、Web サービスの実装に関する複雑さを隠すことができました。

近いうちに皆さんは昇進するかもしれません。


ダウンロード

内容ファイル名サイズ
The PHP web service file used in this articlewebservice.php1KB
The client HTML/JavaScript codeclient.html2KB

参考文献

学ぶために

製品や技術を入手するために

  • Dojo Toolkit を試してみてください。
  • NuSOAP ライブラリーを入手してください。

議論するために

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Web development, Open source
ArticleID=513841
ArticleTitle=Dojo を使って Web サービスのレスポンスを処理する
publish-date=07272010