JavaScript Webサービスクライアントを記述する
以降では、RectangleArea
メソッドを題材として、JavaScriptとAJAX技術を使ってブラウザWebサービスクライアントを作成する方法について説明します(TriangleArea
メソッドの呼び出しも基本的には同じです)。
まず、RectangleArea
メソッドの幅および高さの引数値を指定するための、シンプルなHTMLインターフェースを記述することから始めます。インターフェースに入力された値は、myAjax
というJavaScript関数に渡します(この関数は、ajaxSOAP
という名前の独立したJavaScriptモジュールに書かれています)。このHTMLには空白の<div>
タグが含まれており、AJAXはここにWebサービスサーバから受信した応答を入れます。最小限のインターフェースを以下に示します(これをwebserviceフォルダに保存してください)。
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="content-type" content="text/html;charset=UTF-8"> <title>Web Service SOAP and AJAX</title> </head> <script type="text/javascript" src="./ajaxSOAP.js"></script> <body> <div style="position:relative;left:0px; top:-12px;background-color:#1D3968;margin:0px;"> <h2 align="center"><font color="#ffffff"> Consume WebServices through SOAP-AJAX calls</font></h2></div> <table align="center" cellpading="0px" cellspacing="3px" bordercolor="#000000" border="0" style="position:relative;width:300px;height:200px;"> <tr> <td colspan="2" align="center"><h1>Rectangle Area</h1></td> </tr> < tr> <td valign="center"><font color="#cc0000" size="3"> Insert value for l:</font></td> <td><input id="l_id" type="text"></td> </tr> <tr> <td><font color="#cc0000" size="3">Insert value for L:</font></td> <td><input id="L_id" type="text"></td> </tr> <tr> <td><input type="button" value="Calculate Area" onclick="myAjax();"></td> </tr> <tr> <td colspan="2"> <div id="resultDiv"></div> </td> </tr> </table> </body> </html>
このコードにはmyAJAX
関数の実装が含まれていませんが、心配は無用です。これについては次に行います。空のJavaScriptモジュールを作成し、「ajaxSOAP.js」と名づけます。このモジュールを、前のHTMLコードと同じwebserviceフォルダに保存します。
MyAJAX
関数では、まず、Webサービスサーバに渡す必要がある引数を抽出します。前述のとおり、引数の値はHTMLインターフェースを通じて提供されるので、l_id
とL_id
というIDで識別される2つのテキストフィールドにアクセスします。
var l_var = document.getElementById("l_id").value; var L_var = document.getElementById("L_id").value;
引数の値を取得したら、SOAPメッセージを記述する必要があります。このシンプルなSOAPメッセージでは、RectangleArea
メソッドを呼び出して、面積の計算に必要な2つの値を渡します。今回の例では、このSOAPメッセージをJavaScript変数に格納しておきます。
soapMessage = ' <?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope SOAP-ENV:encodingStyle= "http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tns="urn:mathwsdl"> <SOAP-ENV:Body> <tns:RectangleArea xmlns:tns="urn:mathwsdl"> <L xsi:type="xsd:int">' +L_var+'</L> <l xsi:type="xsd:int">'+l_var+'</l> </tns:RectangleArea> </SOAP-ENV:Body> </SOAP-ENV:Envelope>';
次に、AJAXメカニズムを実装します。標準的なアプローチに従い、まずXMLHttpRequestオブジェクトを取得し、サーバのURLでPOSTチャネルを開きます。さらに、callbackAjax
というAJAXコールバック関数を参照するようにします。
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=callbackAjax;
次に示す3行のコードは、AJAX実装ではあまり見かけないものです。これらはWebサービスの呼び出しの成否にかかわる3つのHTMLヘッダーです。ここでは特に、メッセージに呼び出し(SOAP要求)が含まれることを表すMessageTypeヘッダーを指定する必要があることを覚えておいてください。
httpRequest.setRequestHeader("Man", "POST http://localhost/php/webservice/nusoap_server.php HTTP/1.1") httpRequest.setRequestHeader("MessageType", "CALL"); httpRequest.setRequestHeader("Content-Type", "text/xml");
最後に、SOAP要求を送信し、応答を待機します。
httpRequest.send(soapMessage);
これで、AJAXメカニズムの要求側の処理は完了です。応答側は、従来どおりの方法で実装します。
下記のcallbackAjax
関数は、Webサービス応答を取得し、書式化を行い、HTMLで作成したresultDiv
タグに結果を表示します。応答もSOAPメッセージの形をしていますが、ほとんどのブラウザはSOAPメッセージの解析方法を把握しているので、ペイロード(有益な情報)のみを抽出できます。しかし、相手側がWebサービスであり、SOAP XMLのチャンクを含む応答を取得する場合には、SOAPメッセージパーサーを実装する必要があります(responseText
ではなくresponseXML
プロパティを使用して応答を抽出し、XML DOMパーサーを使用して必要な情報のみを抽出します)。
function callbackAjax(){ try { if(httpRequest.readyState==4) { if(httpRequest.status==200) { clearTimeout(xhrTimeout); resultDiv=document.getElementById("resultDiv"); resultDiv.style.display='inline'; resultDiv.innerHTML='<font color="#cc0000" size="4"><b>'+httpRequest.responseText+'</b></font>'; } } } catch(e) { alert("Error!"+e); } }
リスト3に、ajaxSOAP.jsモジュールの完全なコードを示します。
var httpRequest = null; var xhrTimeout = null; var url = "http://localhost/php/webservice/nusoap_server.php"; var soapMessage = null; function myAjax() { var l_var = document.getElementById("l_id").value; var L_var = document.getElementById("L_id").value; soapMessage = ' <?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope SOAP-ENV:encodingStyle= "http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tns="urn:mathwsdl"> <SOAP-ENV:Body> <tns:RectangleArea xmlns:tns="urn:mathwsdl"> <L xsi:type="xsd:int">' +L_var+'</L> <l xsi:type="xsd:int">'+l_var+'</l> </tns:RectangleArea> </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=callbackAjax; httpRequest.setRequestHeader("Man", "POST http://localhost/php/webservice/nusoap_server.php HTTP/1.1") httpRequest.setRequestHeader("MessageType", "CALL"); httpRequest.setRequestHeader("Content-Type", "text/xml"); httpRequest.send(soapMessage); xhrTimeout=setTimeout("ajaxTimeout(httpRequest);",120000); } function callbackAjax(){ try { if(httpRequest.readyState==4) { if(httpRequest.status==200) { clearTimeout(xhrTimeout); resultDiv=document.getElementById("resultDiv"); resultDiv.style.display='inline'; resultDiv.innerHTML='<font color="#cc0000" size="4"><b>' + httpRequest.responseText+'</b></font>'; } } }catch(e) { alert("Error!"+e); } } function ajaxTimeout(ajaxOBJ) { ajaxOBJ.abort(); }
リスト3の前半にあるxhrTimeout
変数とajaxTimeout
関数はオプションです。これらはAJAXの堅牢性を高める目的で用意したもので、要求/応答にかかる時間が120,000ミリ秒を超えた場合はコールバックメカニズムを停止します。通常は、120,000秒あれば十分に応答を得ることができます。要求/応答に120,000秒以上かかる場合は、サーバのクラッシュや、通信の使用不可など、何らかの支障があることをクライアントに通知します。