
In this post I'm going to show you how to get started with a JavaScript service, and consume that service inside another JavaScript (A client) embedded in an HTML page.
The scenario I'm going to cover is, developing a JavaScript based service for getting stock updates, which retrieve the stock information by invoking another external web service , and writing a JavaScript client inside an HTML, which invokes the JavaScript service.
Writing the service
1. Download WSO2 Mashup Server binaries and extract into a convenient location (Hereafter referred to as MS_HOME )
2. The JavaScript service should be written as a standard JavaScript file, as mentioned below
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* | |
*/ | |
function getQuote(stockSymbol) { | |
if (stockSymbol == "") | |
throw ("A 'stock symbol' must be specified."); | |
//create new WSRequest object for requesting stock details | |
var stockQuoteRequest = new WSRequest(); | |
var options = new Array(); | |
options["useSOAP"] = 1.1; | |
options["HTTPMethod"] = "POST"; | |
options["useWSA"] = "1.0"; | |
//SOAP action of the StockQuote Web Service | |
options["action"] = "http://www.webserviceX.NET/GetQuote" | |
//create payload for StockQuote Web Service | |
var payload = | |
<GetQuote xmlns="http://www.webserviceX.NET/"> | |
<symbol>{stockSymbol}</symbol> | |
</GetQuote>; | |
try { | |
// endpoint of the StockQuote external service | |
var endpoint = "http://www.webservicex.net/stockquote.asmx"; | |
//open request with synchronous option | |
stockQuoteRequest.open(options, endpoint, false); | |
stockQuoteRequest.send(payload); | |
} catch(ex) { | |
print(ex); | |
throw("There was an error accessing the remote service '" + endpoint + "', The Exception was : " + ex); | |
} | |
var wx = new Namespace("http://www.webserviceX.NET/"); | |
var response = stockQuoteRequest.responseE4X..wx::GetQuoteResult.text(); | |
var stock = new XML(response.toXMLString()); | |
// extracting only few parameters, rest can be done in the same pattern | |
var symbol = stock.Stock.Symbol; | |
var name = stock.Stock.Name; | |
var last = stock.Stock.Last; | |
var previous = stock.Stock.PreviousClose; | |
var change = stock.Stock.Change; | |
var earns = stock.Stock.Earns; | |
var result = "symbol:"+symbol+":name:"+name+":last:"+last+":previous:"+previous+":change:"+change+":earns:"+earns; | |
// print the generated result | |
print("Result : " + result); | |
return result; | |
} |
3. This JavaScript file (stockQuote.js) needs to be placed in the following location
<MS_HOME>/repository/deployment/server/jsservices/admin
4. Start the server ($ sh
5. If the StockQuote service is deployed successfully it should be logged as "Deploying Web service: stockQuote.js" and verify through Management Console (https://localhost:9443/carbon/service-mgt/index.jsp?region=region1&item=services_list_menu, or http://localhost:9763/services/admin/stockQuote?wsdl)
6. After successfully starting up the server, note that a folder is created in <MS_HOME>/repository/deployment/server/jsservices/admin with the name stockQuote.resources.
Create a new folder with the name "www" if such a folder is not there already. Service client related code should be place in that folder.
Writing Client code and Installing a custom UI
JavaScript clients can invoke services via generated stubs. The generated stub is again a JavaScript file. It can viewed as follows,
http://localhost:9763/services/admin/stockQuote?stub
1. The sample code of StockQuote service client is listed below, note that it is embedded in an HTML file (which is the UI of your service) and in the top you can see a reference to the generated stub is included. Save this as index.html file into the "www" folder created above.
<MS_HOME>/repository/deployment/server/jsservices/admin/stockQuote.resources/www
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<title>Stock Quote Service</title> | |
<script type="text/javascript" src="?wsdl2form&contentType=text/javascript&resource=js/WSRequest.js"></script> | |
<!-- Import JavaScript stub --> | |
<script type="text/javascript" src="../stockQuoteStub?stub"> | |
</script> | |
<script type="text/javascript"> | |
function load(symbolValue) { | |
var stockDetails = services["admin/stockQuote"].operations["getQuote"]; | |
var payload = "<GetQuote xmlns:p=\"http://services.mashup.wso2.org/stockQuote?xsd\"><stockSymbol>"+symbolValue+"</stockSymbol><GetQuote>"; | |
stockDetails.callback = function(payload) { | |
var responseJSON = WebService.utils.xml2bf(payload); | |
var result = responseJSON["ws:getQuoteResponse"].return.$; | |
// result is returned as a concatenated string, seperated by ":" | |
var stringArray = result.split(":"); | |
var str = ""; | |
for(i = 0; i < stringArray.length - 1; ){ | |
str = str + "<br/>" + stringArray[i] + " = " + stringArray[i+1]; | |
i = i + 2; | |
} | |
// populate the results in an HTML table | |
document.getElementById("TableHolder").innerHTML = str; | |
}; | |
stockDetails.onError = handleError; | |
stockDetails(payload); | |
} | |
function handleError(error) { | |
log (document.getElementById('console'), "Fault: " + error.reason + "\n\n" + error.detail); | |
} | |
function log(console, data) { | |
var browser = WSRequest.util._getBrowser(); | |
if (browser == "ie" || browser == "ie7") | |
console.innerText = data; | |
else | |
console.textContent = data; | |
} | |
</script> | |
</head> | |
<body> | |
<input name="textbox1" id="textbox1" type="text" /> | |
<input name="buttonExecute" onclick="load(document.getElementById('textbox1').value)" type="button" value="Clickme" /> | |
<div id="console"></div> | |
<div id="TableHolder"></div> | |
</body> | |
</html> |
2. Access the UI of the as follows to test the functionality
http://localhost:9763/services/admin/stockQuote/
In the text box, input a Stock symbol (eg: GOOG, IBM, VRTU .. etc) and check the results
Troubleshooting
In some situations, the generated JavaScript stubs are having some issues (which are already identified and will be fixed in the next release)
In such a scenario, as a hack you can do the following.
1. Access the stub (http://localhost:9763/services/admin/stockQuote?stub) and save the stub file in <MS_HOME>/repository/deployment/server/jsservices/admin/stockQuote.resources/www location as "stockQuoteStub.js"
2. The "bf2xml" function of the stub is the culprit here, so as a fix replace the relevant code related to bf2xml function with the code below
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
bf2xml : function (json) { | |
if (typeof json !== "object") return null; | |
var cloneNS = function(ns) { | |
var nns = {}; | |
for (var n in ns) { | |
if (ns.hasOwnProperty(n)) { | |
nns[n] = ns[n]; | |
} | |
} | |
return nns; | |
}; | |
var processLeaf = function(lname, child, ns) { | |
var body = ""; | |
if (child instanceof Array) { | |
for (var i = 0; i < child.length; i++) { | |
body += processLeaf(lname, child[i], cloneNS(ns)); | |
} | |
return body; | |
} else if (typeof child === "object") { | |
var el = "<" + lname; | |
var attributes = ""; | |
var text = ""; | |
for (var key in child) { | |
if (child.hasOwnProperty(key)) { | |
var obj = child[key]; | |
if (key === "$") { | |
text += obj; | |
} else if (key === "@xmlns") { | |
for (var prefix in obj) { | |
if (obj.hasOwnProperty(prefix)) { | |
if (prefix === "$") { | |
if (ns[prefix] !== obj[prefix]) { | |
attributes += " " + "xmlns=\"" + obj[prefix] + "\""; | |
ns[prefix] = obj[prefix]; | |
} | |
} else if (!ns[prefix] || (ns[prefix] !== obj[prefix])) { | |
attributes += " xmlns:" + prefix + "=\"" + obj[prefix] + "\""; | |
ns[prefix] = obj[prefix]; | |
} | |
} | |
} | |
} else if (key.indexOf("@") === 0) { | |
attributes += " " + key.substring(1) + "=\"" + obj + "\""; | |
} else { | |
body += processLeaf(key, obj, ns); | |
} | |
} | |
} | |
body = text + body; | |
return (body !== "") ? el + attributes + ">" + body + "" : el + attributes + "/>" | |
} | |
}; | |
for (var lname in json) { | |
if (json.hasOwnProperty(lname) && lname.indexOf("@") == -1) { | |
return processLeaf(lname, json[lname], {}); | |
} | |
} | |
return null; | |
}, |
3. In index.html file modify the line which has the reference to the stub, so remove the line
and add the following line instead
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script src="stockQuoteStub.js" type="text/javascript"> | |
</script> |
Note that, now it is referenced the modified version of the stub, which is in the www directory
4. Now the issue should be fixed.