Build enterprise SOA Ajax clients with the Dojo toolkit and JSON-RPC

Learn how to use the Dojo toolkit to build enterprise SOA clients for Java™ Platform, Extended Edition (Java EE) applications, and the the JavaScript Object Notation–RPC (JSON-RPC) to invoke server-side Java objects.

Share:

Introduction

Asynchronous JavaScript and XML (Ajax) is a new way to build rich Web applications using native browser technology. For developers coding complex applications that require some type of "alive" user interface, JavaScript has been the way to go. However, JavaScript is difficult to code, debug, make portable, and maintain. Using an Ajax toolkit can help minimize many of the common issues with JavaScript and Ajax. Good Ajax toolkits provide a set of reusable widgets, a framework for extending and creating widgets, an event system, JavaScript utilities, and enhanced asynchronous server invocation support. In this paper, we'll talk about using the Dojo toolkit for building enterprise SOA clients for Java EE applications. We'll also use JSON (JavaScript Object Notation)–RPC to invoke the server-side Java objects.

In this paper, I'll also give you a brief introduction to Ajax, Dojo, JSON, and JSON-RPC, as well as some design principles for designing Ajax applications, and a brief example you can download and try for yourself.


Ajax overview

There are many papers, articles, and books on Ajax. I won't go into a deep introduction to Ajax. For more detailed information, check out Resources.

Ajax is as architectural style for building Web sites using native browser components. The key elements of Ajax are:

  • JavaScript, which orchestrates the Ajax user experience.
  • Cascading Style Sheets (CSS), which define the visual style of page elements.
  • Document Object Model (DOM), which presents the structure of Web pages as a set of programmable objects that can be manipulated with JavaScript.
  • XMLHttpRequest, which enables the retrieval of data from Web resources as a background activity.

The XMLHttpRequest object is the key element.

XMLHttpRequest Object

The XMLHttpRequest object is the mechanism used by Ajax to make asynchronous requests. Figure 1 illustrates the flow:

Figure 1. A flowchart of the XMLHttpRequest object making asynchronous requests
A flowchart of the XMLHttpRequest object making asynchronous requests.

The XMLHttpRequest object is a JavaScript object that is available in the browser. (Microsoft™ and Mozilla browsers each have their own version). The flow is as follows:

  1. A page invokes some JavaScript.
  2. The JavaScript function creates an XMLHttpRequest object. This includes setting up a URL to invoke and HTTP request parameters.
  3. The JavaScript function registers a callback handler. The HTTP response invokes this callback handler.
  4. The JavaScript function invokes the send method on the XMLHttpRequest object, which in turn sends an HTTP request to a server.
  5. The XMLHttpRequest object immediately returns control to the JavaScript method. At this point the user can continue working with the page.
  6. Sometime later, the HTTP server returns an HTTP response, invoking the callback handler.
  7. The callback handler has access to the HTML DOM object. It can update the page elements on the fly without interrupting the user (unless you happen to update the DOM object the user is working on).

Asynchronous requests can also be made locally, updating the DOM of the page asynchronously.


Dojo toolkit overview

Dojo enables you to easily build dynamic sites. It provides a rich widget library you can use to compose your pages. You can use Dojo's aspect-based event system to attach events to components to create a rich interaction experience. In addition, you can use several Dojo libraries to make asynchronous server requests, add animation effects, browser storage utilities, and many more.

Dojo widgets

Dojo provides a rich set of widgets you can use to build pages. You can create Dojo widgets in several ways. One of the many benefits of Dojo is that it allows you to use standard HTML tags. You can then make these tags into widgets. This allows HTML developers to easily use Dojo, as seen in Listing 1:

Listing 1. Using Dojo in HTML tags
<div dojoType="FloatingPane" class="stockPane" title="Stock Form" id="pane" 
                                 constrainToContainer="true" displayMaximizeAction="true">
       <h2>Stock Service</h2>
       Enter symbol: <input dojoType="ValidationTextBox" required="true"
                                          id="stockInput">
       <p />
       <button dojoType="Button2" widgetId="stockButton">
               Get Stock Data
       </button>
       <div id="resultArea" />
</div>

You can use the div tag to define widget locations and Dojo will place the widget there either during page load or in response to events. You can also use more specific tags, such as <dojo:widget>, and add Dojo widget properties to them. In Listing 1, we added the dojoType attribute to the button tag. Once you mark up your tags, you need to load the widget inside some JavaScript, as shown in Listing 2. You can embed the tags inside of the page, but I recommend putting it inside a separate JS file. Later in the article, we'll illustrate some MVC design principles.

Listing 2. Using Dojo in HTML tags
//require statements
dojo.require("dojo.widget.*" );
dojo.require("dojo.event.*");
dojo.require("dojo.widget.Button2");
dojo.require("dojo.widget.FloatingPane" );

//all dojo.require above this line
dojo.hostenv.writeIncludes(); 
dojo.require();

You can create, access, modify, and destroy widgets in JavaScript, allowing for much dynamic behavior. You'll see an example of accessing widgets in JavaScript in our example.

The Dojo event system

The Dojo event system uses aspect-oriented technology to attach events to widgets. This decouples the widgets from the actual event handling. Rather than hard-code JavaScript events onto the html tags, Dojo provides an API that allows you to attach events to widgets, as seen in Listing 3.

Listing 3. Using Dojo to attach an event handler to a widget
function submitStock()
	{
		...
	}
function init()
	{
		var stockButton = dojo.widget.byId('stockButton');
		dojo.event.connect(stockButton, 'onClick', 'submitStock');
	}
dojo.addOnLoad(init);

By using the connect method, you can connect a JavaScript method to a widget. You can also attach dojoAttachEvent on a div node as shown below. Certain HTML tags do not have events defined, so this is a handy extension.

Listing 4. Using Dojo to attach an event to an HTML tag
<div dojoAttachPoint="divNode"
    dojoAttachEvent="onClick; onMouseOver: onFoo;">

The Dojo event system also allows for more advanced features, such as:

  • Declaring advices to inject event handlers before or after existing ones.
  • Allowing widgets to subscribe or publish to topics in the browser.
  • Adding event callbacks.
  • Normalized event objects you can use to represent events.

For more information, check out: http://dojo.jot.com/EventExamples.

Dojo asynchronous server request

Dojo provides an easy way to make asynchronous requests to the server by abstracting out the browser-specific details. Dojo allows you to create a data structure to hide the details, as showin in Listing 5.

Listing 5. Asynchronous requests with Dojo
var bindArgs = {
    url:        "/DojoJ2EE/MyURI",
    mimetype:   "text/javascript",
    error:      function(type, errObj){
        // handle error here 
    },
    load:      function(type, data, evt){
        // handle successful response here
    }
};
// dispatch the request
var requestObj = dojo.io.bind(bindArgs);

In addition, Dojo supports RPC using the JSON-RPC standard. We'll look at Dojo's support for JSON in the next section.

Additional Dojo functionality

Dojo is a rich library with tons of functionality, including:

  • General purpose libraries that handle html, string, style, dom, regular expression, and several other utilities.
  • Data structures that include Dictionaries, ArraryLists, Queues, SortedList, Sets, and Stack.
  • Visual Web utilities to add animation affects, validation, drag and drop, and several others.
  • Math and cryptography libraries.
  • Storage components.
  • XML parsing

For more information, see http://manual.dojotoolkit.org/index.html.


JSON overview

JSON is a subset of the object literal notation of JavaScript and is a common way to represent data structures in JavaScript. JSON is a text format that is completely language independent, but uses conventions that are familiar to programmers of the C family of languages, including C, C++, C#, Java, JavaScript, Perl, Python, and many others. These properties make JSON an ideal data-interchange language for Ajax clients.

JSON is built on two structures:

  1. A collection of name/value pairs. In various languages, this is realized as an object, record, struct, dictionary, hash table, keyed list, or associative array.
  2. An ordered list of values. In most languages, this is realized as an array, vector, list, or sequence.

Below is an example of a JSON object:

var myJSONObject = {"id": 4, "name": "Roland Barcia", "pets": ["dog","cat","fish"]};

In the example, we have named value pairs. Anything in brackets is a list. There are a rich set of implementations in various programming languages. For more information, see http://json.org/

JSON-RPC

JSON-RPC is a lightweight remote procedure call protocol in which JSON serializes requests and responses. Sending a request to a remote service invokes a remote method. The request is a single object with three properties:

  • method - A string containing the name of the method to be invoked.
  • params - An array of objects to pass as arguments to the method.
  • id - The request ID. This can be of any type. It is used to match the response with the request that it is replying to.

When the method invocation completes, the service must reply with a response. The response is a single object with three properties:

  • result - The object that was returned by the invoked method. This must be null, in case there was an error invoking the method.
  • error - An error object if there was an error invoking the method. It must be null, if there was no error.
  • id - This must be the same ID as the request it is responding to.

A notification is a special request that does not have a response. It has the same properties as the request object with one exception:

  • id - Must be null.

JSON vs. XML

XML is a common transport for service-oriented architecture (SOA) and data transfer. Certainly, many services exist today in SOAP format. However, there is a split in the Ajax community when it comes to data transfer. JSON has several advantages:

  • Browsers parse JSON faster than XML.
  • JSON constructs are programming-language friendly and easier to translate to back-end programming languages like Java.
  • JSON is fairly stable. Additions to JSON are supersets.

XML has the following advantages:

  • Calling existing services that use XML as a transport already.
  • XML can be transformed on the fly using XSLT. This is ideal in an Enterprise Service Bus (ESB) scenario.

JSON-RPC for Dojo

Dojo provides an abstraction layer for invoking JSON-RPC requests. JSON-RPC for Dojo introduces the notion of a Standard Method Description (SMD). An SMD file is a description of a JSON-RPC service. It allows you to describe a JSON invocation in a neutral fashion. Listing 6 gives an example of such a JSON invocation:

Listing 6. A JSON invocation in Dojo
{"SMDVersion":".1",
 "objectName":"StockService",
 "serviceType":"JSON-RPC",
 "serviceURL":"/DojoJ2EE/JSON-RPC",
 "methods":[
		{"name":"getStockData",
		"parameters":[
			{"name":"symbol",
			"type":"STRING"}
		 ]
    }
  ]
 }

You can use the Dojo API to invoke the service:

var StockService = new dojo.rpc.JsonService("/path/to/StockService.smd"); StockService.getStockData("IBM",stockResultCallback);

Over the wire, this will send this structure:

{"id": 2, "method": "getStockData", "params": ["IBM"]}

JSON-RPC Java ORB

JSON-RPC defines a standard format for remote procedure calls, but there is no standard mapping to a back-end technology. JSON-RPC Java Orb provides a mechanism to register Java Objects and expose them as JSON-PRC services. It also provides a client API in JavaScript to invoke the services.

If you choose to use Dojo, you can write your own binding code. The JSON API for Java can help. For more information, see (http://developer.berlios.de/projects/jsontools/). In our example, we'll use JSON-RPC Java ORB to make asynchronous requests to take advantage of the server side binding code.

JSON-RPC Java Orb allows you to register Java objects inside one of the servlets scopes (request, session, application). It can then use the JSON-RPC request to invoke the Java object. It does this by pre-pending the object type to the JSON object. Since the Dojo API does not do this, the Dojo client API for JSON-RPC is incompatible with JSON-RPC for Java.

Listing 7 gives an example of how you could register a Java object with an HttpSession:

Listing 7. An HttpSession registering a Java object
HttpSession session = sessionEvent.getSession();
JSONRPCBridge json_bridge = null;
json_bridge = (JSONRPCBridge) session.getAttribute("JSONRPCBridge");
if(json_bridge == null) {
		json_bridge = new JSONRPCBridge();
		session.setAttribute("JSONRPCBridge", json_bridge);
}
json_bridge.registerObject
("StockService",StockServiceImpl.getStockService());

You can do this in a servlet, or in an HttpListener. You can then write a JavaScript client to your Java service, as shown in Listing 8.

Listing 8. A JSONRpcClient connecting to a Java Service
jsonrpc = new JSONRpcClient("/DojoJ2EE/JSON-RPC");
var stockButton = dojo.byId('stockInput');
jsonrpc.StockService.getStockData(stockResultCallBack,stockButton.value);

This request sends the following payload:

{"id": 2, "method": "StockService.getStockData", "params": ["IBM"]}

The response looks like this:

{"result":{"javaClass":"com.ibm.issw.json.service.StockData","price":100, "companyName":"International Business Machine","symbol":"IBM"},"id":2}

The JSON-RPC for Java client handles this and gives you a static interface.

In order to support requests, you need to register a special servlet. I'll show you how to do this later.

One downside of the JSON-RPC Java ORB is the fact that there is a single URL, which makes it difficult to use Java EE security to secure the URL. As a work-around, you can register services at the HTTP session layer, and add them based on security.


Build an enterprise client for enterprise applications

In this section, I'll go over some design principles and then go through an example. You can download the completed WAR file and try the application for yourself.

Model View Controller

In the Java EE world, Model View Controller (MVC) has become very mature thanks to frameworks like Struts and JavaServer Faces. The use of Ajax makes proper MVC design critical to successful Web applications. In addition, SOA allows the possibility of invoking a service directly from Ajax applications. This has several advantages, as described in the WebSphere Journal article "AJAX Requests – Data or Markup?".

Figure 2 gives a high-level overview of an ideal ecosystem between Ajax client and Java EE applications.

Figure 2. An ideal ecosystem between Ajax client and Java EE applications
An ideal ecosystem between Ajax client and Java EE applications.

On the server side, business and portal functions are now exposed as some type of service interface. Underneath the services, proper server-side best practices should be followed. Server applications should expose course grain services. Frameworks like JavaServer Faces are now responsible for doing the initial rendering; however, this is optional with client side Ajax toolkits.

On the browser, it is important to have a separation of concerns. Figure 3 highlights the Java Server file structure:

Figure 3. The Java Server file structure
The Java Server file structure.

You may choose to have a single JavaScript Controller per page. However, for complicated Portal Pages, you can group related events into a small set of controllers.

The controller file should:

  1. Load wire request handlers to widgets, as shown in Figure 4:
    Figure 4. Attaching request handlers to widgets
    Attaching request handlers to widgets.
  2. Implement the request handlers. The request handlers should not have too much logic. They should delegate to a service facade for interactions to the back end.
  3. Implement callback handler methods. The callbacks should delegate rendering to a separate JS file. In addition, they should delegate storing an intermediate state to a separate Java Server file. For stateless interactions, the results can be passed directly to the rendering.js file.

Figure 5 illustrates the flow between the components:

Figure 5. Flow of information from the client through request handlers, and then through callback handlers
Flow of information from the client through request handlers, and then through callback handlers.

The rendering file contains the logic for rendering components or user interfaces based on the result of an event.

The Business Facades should contain methods that the proxy server requests. The DataCopy should maintain local view objects that need to exist locally in the browser.

Set up a Java EE application for Dojo

With Dojo, you have to add the JavaScript files as part of the Web application. You can copy the dojo folder into your Web application folder as shown in Figure 6:

Figure 6. Add the JavaScript files necessary to use Dojo
Add the JavaScript files necessary to use Dojo.

Set up a Java EE application for JSON-RPC Java Orb

In order to use the JSON-RPC Java Orb in your application, you need to add the json-rpc-1.0.jar in the lib directory of the Web app. You also need to add a single jsonrpc.js file into your Web content folder, as showin in Figure 7:

Figure 7. Add the JavaScript file necessary to use the JSON-RPC Java Orb
Add the JavaScript file necessary to use the JSON-RPC Java Orb.

In order to enable your Java EE application to receive JSON-RPC for Java requests, you have to add the JSONRPCServlet as shown in Listing 9:

Listing 9. Code needed to use the JSONRPCServlet
<servlet>
	<servlet-name>
		com.metaparadigm.jsonrpc.JSONRPCServlet
	</servlet-name>
	<servlet-class>
		com.metaparadigm.jsonrpc.JSONRPCServlet
	</servlet-class>
</servlet>

<servlet-mapping>
	<servlet-name>
		com.metaparadigm.jsonrpc.JSONRPCServlet
	</servlet-name>
	<url-pattern>/JSON-RPC</url-pattern>
</servlet-mapping>

Think SOA

Ajax makes a perfect SOA client. In our example, we use a simple Java service.

Java service

Figure 8 is a model of the Java-based service:

Figure 8. A model of the Java-based service
A model of the Java-based service.

We use a simple hard-coded implementation as shown in Listing 10:

Listing 10. A simple hard-coded Java service
public StockData getStockData(String symbol) throws StockException {
	if(symbol.equals("IBM"))
	{
		StockData stockData = new StockData();
		stockData.setCompanyName("International Business Machine");
		stockData.setSymbol(symbol);
		stockData.setPrice(100.00);
		return stockData;
	}
	else
	{
		throw new StockException("Symbol: " + symbol + " not found!");
	}	
}

Expose Java services using JSON-RPC

In order to expose the Java application, I used an HttpSessionListener called ExportServices to register services for the user, as shown in Listing 11:

Listing 11. ExportServices, an HttpSessionListener that exposes the Java service
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
	
import com.ibm.issw.json.service.StockServiceImpl;
import com.metaparadigm.jsonrpc.JSONRPCBridge;
	
public class ExportServices implements HttpSessionListener {
	
	public void sessionCreated(HttpSessionEvent sessionEvent) {
			
		HttpSession session = sessionEvent.getSession();
		JSONRPCBridge json_bridge = null;
		json_bridge = (JSONRPCBridge) session.getAttribute("JSONRPCBridge");
			if(json_bridge == null) {
				json_bridge = new JSONRPCBridge();
				session.setAttribute("JSONRPCBridge", json_bridge);
			}
		json_bridge.registerObject
			("StockService",StockServiceImpl.getStockService());
	}
	
	public void sessionDestroyed(HttpSessionEvent arg0) {
			
	}
	
}

You need to add the listener to the application by adding it to web.xml as shown in Listing 12:

Listing 12. The ExportServices listener added to web.xml
<listener>
	<listener-class>ExportServices</listener-class>
</listener>

Client development process

Now that we've set up the infrastructure and exposed the service, we can build the Web client. With Dojo, we leverage the widgets to build the Web page and leverage the event model. Figure 9 illustrates a suggested development process:

Figure 9. A sample development process
A sample development process.

I'll use this process to demonstrate the sample.

Build the UI from widgets

First, I built the UI. See Listing 13 for a sample UI.

To create the UI:

  1. Load the scripts:
    1. dojo
    2. jsonrpc
    3. StockClientController
    4. resultRenderer
  2. Build the page, using a combination of div and HTML tags to create Dojo widgets.
    Listing 13. The HTML UI
    <html>
    <head>
    <title>Stock Form</title>
    
    <script type="text/javascript" src="../dojoAjax/dojo.js"></script>
    <script type="text/javascript" src="../jsonrpc.js"></script>
    <script type="text/javascript" src="../view/resultRender.js"></script>
    <script type="text/javascript"
    	src="../controller/StockClientController.js"></script>
    <link REL=StyleSheet HREF="../StockApp.css" TYPE="text/css" ></link>
    </head>
    <body>
    
    <div class="layout" dojoType="LayoutContainer">
    <div dojoType="ContentPane" class="stockContent" layoutAlign="bottom"
     id="docpane" isContainer="true" executeScripts="true">
    <div dojoType="FloatingPane" class="stockPane" title="Stock Form" 
    id="pane" constrainToContainer="true" displayMaximizeAction="true">
    			<h2>Stock Service</h2>
    Enter symbol: <input dojoType="ValidationTextBox" required="true"
    			id="stockInput">
    			<p />
    			<button dojoType="Button2" widgetId="stockButton">
    Get Stock Data
    </button>
    			<div id="resultArea" />
    		</div>
    	</div>
    </div>
    </body>
    </html>
  3. StockClientController.js is key. In the beginning of the script, load the required widgets using the dojo.require method and then initialize the Dojo environment, as shown in Listing 14.
    Listing 14. StockClientController initializing the Dojo environment
    //require statements
    dojo.require("dojo.widget.*" );
    dojo.require("dojo.event.*");
    dojo.require("dojo.widget.Button2");
    dojo.require("dojo.widget.FloatingPane" );
    	
    //all dojo.require above this line
    dojo.hostenv.writeIncludes(); 
    dojo.require();

Think before and after

One thing to consider in Ajax is the fact that some user interfaces won't be displayed until events are triggered. However, one practice is to place div tags as place holders. You can then use DOM or Dojo APIs to access this region and add the dynamic UI elements. In our application, I add a simple div for the result:

<div id="resultArea" />

Attach stylesheets

Next, add the styles using CSS. CSS is the standard means of formatting Ajax applications. With CSS, you can apply a style definition to multiple div tags by setting the tags' class attributes to the name of that style. This allows you to re-use your style definitions. Listing 15 shows the stylesheet I used:

Listing 15. Stylesheet used in the UI
@CHARSET "ISO-8859-1";

.layout
{
	width: 100%;
	height: 80%;
}
	
.stockContent
{
	width: 100%; 
	height: 90%;
	background-color: #F0F0F0 ; 
	padding: 10px;
}
	
.stockPane
{
	width: 40%; 
	height: 250px;
}
	
.exceptionMsg
{
	color: #FF0000;
}

Service view

Next, it's a good idea to make sure the UI developer has a view of the service in JavaScript. Dojo does this with SMD, as described earlier. JSON-RPC for Java gives us the ability to call the Java service directly from JavaScript, as shown in Listing 16:

Listing 16. JavaScript calling the Java service directly
<script type="text/javascript" src="../jsonrpc.js"></script>
jsonrpc.StockService.getStockData(stockResultCallBack,stockButton.value);

Build request event handlers

Next, inside the controller JS file, we need to create the event handler and callback handler. The callback handler should be a facade to other work. In our case, the event handler will call our service asynchronously and pass a callback to the method. This abstraction to the XMLHttpRequest object is provided by JSON-RPC-Java. The callback delegates to a renderer when the response is received, as shown in Listing 17:

Listing 17. The callback and event handlers in the controller file
function stockResultCallBack(result,exception) {
	try {
		renderStockResult(result,exception);
	} catch(e) {
		alert(e);
    } 	    
}

function submitStock()
	{
   	try {
		jsonrpc = new JSONRpcClient("/DojoJ2EE/JSON-RPC");
		var stockButton = dojo.byId('stockInput');
		jsonrpc.StockService.
			getStockData(stockResultCallBack,stockButton.value);
	} 
	catch(e) {
		alert(e);
	}
}

Load initial UI and wire request events on load

Next, I use the Dojo magic at page initialization time to connect the widgets to the request handler. See the init method in Listing 18. The dojo.addOnLoad() method allows you to use the same aspect-oriented technique to attach the init method to the page load event.

Listing 18. The init() method
function init()
	{
	var stockButton = dojo.widget.byId('stockButton');
	dojo.event.connect(stockButton, 'onClick', 'submitStock');
	}
dojo.addOnLoad(init);

Render response

The final step is to add the dynamic render response code. I put this in a separate renderer JS file. You can take various approaches to render responses. In our case, we'll use a combination of DOM API and Dojo utilities to build a simple table. We could use one of Dojo's widgets here, but I want to highlight some of the Dojo utilities and data structures using my code for the function renderStockResult in Listing 19.

To create the render response code:

  1. In the renderStockResult function, use the dojo.byId() method to access the resultArea object.
  2. Check for any exceptions; if renderStockResult had one passed to it, it will pass the exception to an error handler and return.
  3. Use the Dictionary (similar to a Java HashMap) and ArrayList Dojo structures to hold the result data.
  4. Pass the structured data to a generic table creator method.
Listing 19. The render response method
dojo.require("dojo.collections.*");
dojo.require("dojo.fx.*");

function renderStockResult(result,exception)
{
	var resultArea = dojo.byId('resultArea');
	if(exception)
	{
		handleStockError(resultArea,exception);
		return;
	}
	
	var symbolHeader = "Symbol:";
	var priceHeader = "Price:";
	var companyNameHeader = "Company Name:";
	
	var headers = new dojo.collections.ArrayList();
	headers.add(symbolHeader);
	headers.add(priceHeader);
	headers.add(companyNameHeader);
	
	var column = new dojo.collections.Dictionary();
	
	column.add(symbolHeader,result.symbol);
	column.add(priceHeader,result.price);
	column.add(companyNameHeader,result.companyName);
	
	var data = new dojo.collections.ArrayList();
	
	data.add(column);
	
	createTableWithVerticleHeading(resultArea,headers,data);
		
}

After we setup the data structures, I invoke a special createTableWithVerticleHeading method In practice, utilities like this should be externalized. Within the method shown below, I use the Dojo Iterator object to loop through the structures and create the table. Another method I want to point out below is dojo.fx.html.fadeShow(table, 200), which allows you to add a fade-in to the printing of the result. This is just a sneak peek of some of the animation. In Listing 20, the Dojo code is in bold.

Listing 20. The table creation method
function createTableWithVerticleHeading(root,headers,data)
{
	
	var oldResult = dojo.byId('resultTable');
	if(oldResult)
	{
		root.removeChild(oldResult);
	}
	var exceptionMsg = dojo.byId('stockExceptionMsg');
	if(exceptionMsg)
	{
		resultArea.removeChild(exceptionMsg);
	}
	var table = document.createElement("table");
	dojo.fx.html.fadeShow(table, 200);
	table.setAttribute("id","resultTable");
	
	root.appendChild(table);
	var headerIter = headers.getIterator();
	
	
	while(!headerIter.atEnd())
	{
		var row = document.createElement("tr");
		table.appendChild(row);
		var element = document.createElement("th");
		element.setAttribute("align","left");
		row.appendChild(element);
		var header = headerIter.get();
		var dataElement = document.createTextNode(header);
		element.appendChild(dataElement);
		var dataIter = data.getIterator();
		while(!dataIter.atEnd())
		{
			var resultItem = dataIter.get();
			var item = resultItem.item(header);
			var elementItem = document.createElement("td");
			elementItem.setAttribute("align","left");
			row.appendChild(elementItem);
			var dataText = document.createTextNode(item);
			elementItem.appendChild(dataText);
		} 	
	}
}

Finally, I add a simple error handling method to print an error message, as shown in Listing 21. Keep in mind that I add the bold text by setting the class attribute on the element and then delegating to the CSS file.

Listing 21. The error handling method
function handleStockError(resultArea,exception)
{
	var oldResult = dojo.byId('resultTable');
	if(oldResult)
	{
		resultArea.removeChild(oldResult);
	}
	var exceptionMsg = dojo.byId('stockExceptionMsg');
	if(exceptionMsg)
	{
		resultArea.removeChild(exceptionMsg);
	}
	var error = document.createElement("h4");
	error.setAttribute("class","exceptionMsg");
	error.setAttribute("id","stockExceptionMsg");
	var errorText = document.createTextNode(exception.message);
	resultArea.appendChild(error);
	error.appendChild(errorText);
	
	return;
}

Test the application

You can download the final WAR file for the application. You can install it in any application server, such as WebSphere Application Server. Once you deploy the application, you can bring up the HTML page to see the floating form, as shown in Figure 10:

Figure 10. A floating form in HTML
A floating form in HTML

Feel free to move the form around. You may notice that I bound the floating to the outer container, as shown in Figure 11:

Figure 11. Floating bound to the outer container
Floating bound to the outer container.

Enter IBM to invoke the Java EE application. The result should be similar to the form shown in Figure 12:

Figure 12. Result of entering IBM into the application
Result of entering IBM into the application.

Next enter some other data to test the error handler, as shown in Figure 13.

Figure 13. Test the error handler
Testing the error handler.

Dojo also provides a Unit Test Suite to do automated unit testing.


Conclusion

In this article, I introduced you to building Ajax clients to Java EE applications using the Dojo toolkit, JSON, and JSON-RPC. I gave an overview of each technology and introduced some design principles. Finally, I provided a sample application. Ajax applications are quickly becoming the SOA client. By using toolkits like Dojo, you can easily build these Web pages.


Acknowledgements

I would like to thank Chris Mitchell for his feedback and review of the article.


Download

DescriptionNameSize
Sample code for this articleDojoJ2EE.war  ( HTTP | FTP )1.8MB

Resources

Learn

Get products and technologies

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into WebSphere on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=WebSphere
ArticleID=132588
ArticleTitle=Build enterprise SOA Ajax clients with the Dojo toolkit and JSON-RPC
publish-date=06282006