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秒以上かかる場合は、サーバのクラッシュや、通信の使用不可など、何らかの支障があることをクライアントに通知します。
