January 10, 2007

Simple AJAX/SOAP application

I wrote a simple application that builds an xml-structure, packages it as a SOAP-message and sends it to a web service in another domain. The web service in the other domain handles the response and sends back a SOAP-message that is received, parsed and printed to output. The web service in the other domain in this example is made and hosted by someone else. The client-side code all resides within a Lotus Notes Form.
I apologize for the bad formatting of the code below which makes it more difficult to read. I have to blame the blog tool for this. It's all XML and Javascript.

Here is the example xml-code packaged as a SOAP-message to send to the remote web service:

<soap:envelope xsi="'http://www.w3.org/2001/XMLSchema-instance'" xsd="'http://www.w3.org/2001/XMLSchema'" soap="'http://schemas.xmlsoap.org/soap/envelope/'">
<soap:body>
<loginnfo xmlns="'http://remotehost/'">
<signatur>login</signatur>
<password>password</password>
<regnr>1234</regnr>
</loginnfo>
</soap:body>
</soap:envelope>

Here is the the SOAP-message received from the remote server:

<soap:envelope xsi="http://www.w3.org/2001/XMLSchema-instance" xsd="http://www.w3.org/2001/XMLSchema" soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:body>
<responsetag xmlns="remote_server">
<responsetagresult>This is the response from the web service</responsetagresult>
</responsetag>
</soap:body>
</soap:envelope>


AJAX-code used to send and receive the SOAP-messages:

var xmlhttp
var url;

/* Create xml http request object */
function createXMLHTTPRequest() {
try {
xmlhttp = new XMLHttpRequest();
} catch (trymicrosoft) {
try {
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch (othermicrosoft) {
try {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
} catch (failed) {
xmlhttp = false;
}
}
}
if (!xmlhttp)
alert("Error initializing XMLHttpRequest!");
}

/* LoadXMLDoc function sets and loads parameters and functions for AJAX calls to the remote server using the POST request method. LOADXMLDoc is called by the send button in the form. */
function loadXMLDoc() {
// Create XML HTTP Request
createXMLHTTPRequest();

// Build the url using field values
buildURL();

// Build xml-structure
var xml = createXMLData();

// Set function to wait for response
xmlhttp.onreadystatechange=xmlhttpChange;

// Open connection with POST
xmlhttp.open('POST', url, true);

// Set request headers for message to send. Depends on the web service
xmlhttp.setRequestHeader('Man', 'POST remoteAddress HTTP/1.1');
xmlhttp.setRequestHeader('Content-Type', 'text/xml');
xmlhttp.setRequestHeader('Content-Length', xml.length);
xmlhttp.setRequestHeader('SOAPAction', 'dependsOnTheWebService');

// Send request using POST
xmlhttp.send(xml);
}

/* Build the URL to the remote server */
function buildURL() {
// Get field values
var sAddress = document.getElementById('sendAddress').value;

url = sAddress;
}

/* xmlhttpChange function listens for a response from the remote server. The response can be either text or xml. If xml is received as below the tags are being parsed and presented as needed. */
function xmlhttpChange() {
// if xmlhttp shows 'loaded'
if (xmlhttp.readyState==4) {
// if 'OK'
if (xmlhttp.status==200) {
// Code block for receving text via HTTP, looking at it and printing to output.
/*
var response = xmlhttp.responseText;
document.getElementById('updateWithResponse').innerHTML = response;
*/
// Code block for receiving XML code via HTTP, grabbing it and printing to output.
var response = xmlhttp.responseXML;
var x = response.getElementsByTagName('responsetagresult');

for (var i=0; i<x.length; i++) {
var result = x[i].childNodes[0].nodeValue;
if (i==0) {
document.getElementById('updateWithResponse').innerHTML = "<b>- - - - - Svar från <span style='color: #FF0000'>" + document.getElementById('host').value + "</span> - - - - - -</b><br><br>";
document.getElementById('updateWithResponse').innerHTML = document.getElementById('updateWithResponse').innerHTML + "responsetagresult: " + result + "<br>";
}
else {
document.getElementById('updateWithResponse').innerHTML = document.getElementById('updateWithResponse').innerHTML + "responsetagresult: " + result + "<br>";
}
}
document.getElementById('updateWithResponse').innerHTML = document.getElementById('updateWithResponse').innerHTML + "<br>";
}
else if (xmlhttp.status==404) alert("URL doesn't exist!")
else alert("Problem connecting to server. Status is "+xmlhttp.status)
}
}

function createXMLData() {
var xmlStructure = document.getElementById('XMLExampleSendCode').value;
return xmlStructure;
}

Currently this doesn't work with Firefox due to some security aspects. That has to do with the fact that it is done over separate domains. I don't know if it is considered as a bug but I do hope so. The error message returned from Firefox is "Uncaught exception: Permission denied to call method XMLHttpRequest.open". However using IE6 works fine.

Learn more at W3Schools Online Web Tutorials. They offer excellent tutorials that's great as either reference material or as getting started guides. Here's the AJAX tutorial and the SOAP tutorial. I also recommend an article series published at IBM DeveloperWorks by Brett McLaughlin, auditor and editor at O'Reilly Media Inc. about AJAX called Mastering AJAX.

Technorati tags:
, , , ,


1 comment:

Anonymous said...

To enable cross browser scripting in Firefox you need to add the following to your script:

try {netscape.security.PrivilegeManager.enablePrivilege('UniversalBrowserRead');} catch(e) {}

and do this:

Type 'about:config' in the address bar.
Then turn the field 'signed.applets.codebase_principal_support' to true.