For a long time I wondered why nobody has created a javascript library for web services. There are all kinds of libraries for REST services, but they're not very developer friendly. I much prefer the structure provided by a WSDL, and with tools like wsdl2java creating stubs for my code is a snap.
IBM's Dojo Soap Library
IBMS's Websphere application server offers a set of dojo extensions in their
web 2.0 feature pack (FEP) which includes a SOAP library. I decided to take a look at it and found that it is quite easy to use although there aren't many examples to be found on the web. There is a sample provided with the feature pack but it uses the declarative dojo notation which doesn't work for everyone depending on what the goal is.
I opted to take a scripting approach since I already know how to invoke web services on the server side, and I wanted to see how it measures up in ease of use. Below is a simple example which retrieves data from a
contacts web service I blogged about a while back.
Setting up the Infrastructure
My setup involved two different boxes - one running the webservice (
axisbox) and another which hosted the HTML and the dojo SOAP library (
dsixedev1). Due to the cross domain security restriction enforced by the browser, I also had to set up a reverse proxy (
lenovobox). Your setup may vary, if everything runs on one box then this part doesn't really matter. Here's what I have in my apache
httpd.conf:
ProxyPass /contacts http://lenovobox:8080/axis2
ProxyPassReverse /contacts http://lenovobox:8080/axis2
ProxyPass /was http://dsixedev1:9080
ProxyPassReverse /was http://dsixedev1:9080
The WSDL is loaded using this code:
var wsdlParser = new ibm_soap.util.WsdlParser();
wsdlParser.parse("contacts.wsdl");
Note that I don't load the WSDL directly from the service because it contains a reference to an external schema:
<xsd:schema>
<xsd:import namespace="http://dsixe.com/blog" schemaLocation="ContactService.ContactInfoPort?xsd=ContactService_schema1.xsd"/>
</xsd:schema>
This reference causes the parser to fail, so I have to manually copy/paste the schema into the WSDL and then save it on the WAS server.
Putting it all Together
Here's a complete listing of the HTML document:
<html>
<head>
<title>DsixE SOAP Sample</title>
<script type="text/javascript" src="dojo/dojo.js" djConfig="isDebug: false, parseOnLoad: true"></script>
<script type="text/javascript">
dojo.require("ibm_soap.widget.SoapService");
dojo.require("dojox.wire.ml.util");
function init() {
var wsdlParser = new ibm_soap.util.WsdlParser();
wsdlParser.parse("contacts.wsdl");
// Create reference to service and set the URL
var myService = new ibm_soap.rpc.SoapService(wsdlParser.smdObj);
myService.serviceUrl = "http://lenovobox/contacts/services/ContactService.ContactInfoPort/";
var params = new dojox.wire.ml.XmlElement("getContact");
params.setPropertyValue("arg0", "ABC123");
deferred = myService.getContact(params);
deferred.addCallback(function(xmlData){
// do something useful with the data here
console.log(xmlData);
var phone = dojo.query("phone",xmlData)[0].textContent;
var name = dojo.query("name",xmlData)[0].textContent;
dojo.byId("contact").innerHTML = name + " " + phone;
});
}
dojo.addOnLoad(init);
</script>
</head>
<body>
<H3> DsixE SOAP Sample - Calling a custom Contacts web service </H3>
This is a pure javascript example of how to invoke a SOAP operation without using declarative dojo markup.
<br><br>
<div id="contact"/>
</body>
</html>
the SOAP response:
<?xml version='1.0' encoding='UTF-8'?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<dlwmin:getContactResponse xmlns:dlwmin="http://dsixe.com/blog">
<return>
<name>Carl</name>
<phone>678 555-1212</phone>
</return>
</dlwmin:getContactResponse>
</soapenv:Body>
</soapenv:Envelope>
and the output it produces:
DsixE SOAP Sample - Calling a custom Contacts web service
This is a pure javascript example of how to invoke a SOAP operation without using declarative dojo markup.
Carl 678 555-1212
Overall I'm really pleased with the way IBM has done this, I've always been leery of REST services because they lack a structured type definition available in a WSDL, and the SOAP approach makes the code much easier to read.