Turbocharge Your Pages with AJAX, Dojo, and Struts

ou’d have to be developing web pages on another planet not to have heard the buzz about AJAX (asynchronous Java and XML). Judiciously employed, AJAX calls can enhance the usability of a site and add functionality to create eye-catching browser client applications. This article will show you how to use AJAX to invoke Struts actions and use Tiles to facilitate the creation of the response that updates the calling page. If you’re new to Struts, Tiles, and Javascript you’ll probably want to get a little background by checking out some of the tutorials or publications noted in the resources section. However, if you’re up to speed on how to write Javascript and you’ve got some Struts and Tiles experience under your belt then you’re ready to read on.

AJAX is actually not a new technology. XML-RPC calls have been around for years. Moreover, web services using SOAP received a lot of attention for a while but never reached the level of hype and intensity that AJAX has for a variety of reasons. It’s hard to pinpoint any single benefit of AJAX that is the cause for such energy in the development community; however, the growing awareness of the benefits of service-oriented architectures and the powerful user interface improvements that AJAX facilitates certainly has something to do with it.

The traditional web request-response model forces a web form submission and a reload (refresh) of the entire page in order to change the data a user is viewing. In contrast, AJAX provides a mechanism for in-place modification of a subsection of the page that often is faster and less of a context shift for the user. Modern browsers create a parse-tree of all the elements on a page (this is the Document Object Model or DOM) and AJAX response processing can selectively update a subsection of the DOM, avoiding an expensive, full reload of the page from the server. The Dojo toolkit (see resources section, in the left column, for download link) is a powerful Javascript API for invoking remote resources (URLs for our purposes) and also provides a robust set of ancillary Javascript utility classes.

What You Need
–Dojo, which may be freely downloaded from http://sourceforge.net/project/showfiles.php?group_id=12867&release_id=67726.
–Basic understanding of AJAX including knowledge of Javascript and XML parsing
–Any Java Web container such as Tomcat or JBoss (Servlet spec 2.4+).
–Some knowledge of the Jakarta Struts Web framework, the Tiles Web framework, and their associated taglibs.

The ability to invoke a remote resource without a full page reload means that user interactions with a page’s data can be incremental. A Web page typically uses the form tag to mark off a portion of the page to submit back to the server. The fields of the form are posted to the resource specified in the action attribute of the form tag. While Dojo does support sending or submitting a ‘form node’ to refresh/replace data on a page, this isn’t required. (The code samples I’ll be discussing shortly will demonstrate this.) The HTML spec also provides a div tag that allows for a non-form tag delimited node to be demarcated on a page. The data in the div is what is typically updated or replaced when the AJAX response is received from the server.

Dojo configuration is fairly simple. The main dojo.js Javascript resource file sits on your web server and you reference it in your pages. Including a Javascript block like the one below tells Dojo where to “find itself.”

  var djConfig = {           baseRelativePath: "js/dojo",           isDebug: true,           preventBackButtonFix: false };

The isDebug flag, when set to ‘true,’ forces useful debug information to print to the page being loaded. The /src directory resides where this base path points ensuring that Dojo can access the libraries you reference in your scripts.

A base template can be defined in the tiles-def.xml to specify Dojo and other Javascript resource files in a reusable way. Other tiles can reuse this ‘root’ tile by extending. Below is the ‘root’ tile’s definition.

           

The basic.jsp tile (see the sample code [[will add link]] accompanying this article) includes a Struts logic tag to read the argument that the tiles-def.xml ‘putList’ element passes to the tile.

                                                

Other tiles extending this base tile automatically include the appropriate Dojo Javascript resource references by passing the desired script names as additions to the reusableJavascripts list in their own tile definition in the tiles-def.xml.

                                                                  

Using Tiles to add the Javascript resource file references reduces the likelihood of typos or incorrect locations being specified inadvertently. It also makes your application more maintainable because it centralizes these definitions so developers don’t have to look at individual Javascript pages to determine the .js resources being utilized.

As an aside, Dojo configuration for local development (without a web server) requires a slightly different approach. Be advised that the notation for the URI to the local Dojo resources (dojo.js) is browser sensitive. (I found this out the hard way.) The markup below (with comments) sums it up.

A Sorted Example
In order to understand how Dojo works with Struts and Tiles it will help to have a concrete problem to solve. To this end, the accompanying sample code introduces a list of famous people and displays it to the user as shown in Figure 1.

Dojo Woes: Living on the Bleeding Edge

While I really like Dojo, I did experience some difficulties with the back button and some rather unhelpful debug statements. I first installed Dojo 0.2.2 and had some issues getting the dojo.byId calls to work. Struts doesn’t support the id property as a property of the html:hidden tag. IE blows right by this missing property during a dojo.byId(“field”) call and looks at the field’s name. Firefox on the other hand throws an error and informs you that the field doesn’t support any such property?meaning id. I’m extremely fortunate that one of my colleagues clued me in that the styleId field is the html:hidden tag’s property that converts to id once the JSP renders. I also lucked out during the same conversation when another colleague mentioned that the changeUrl parameter must be added to the dojo.bind( ) method in order to get some semblance of back button functionality running.

If this is all starting to seem like work to you – you’re not alone. As I noted, some colleagues of mine were very generous with their expertise in filling me in about the various hacks they performed to get the back button working. Even with their pointers I put in more hours than I care to remember hacking through some of these issues and new ones still pop up from time to time. I wish I could report that I got to the bottom of them all prior to going to press and that the sample code I wrote will clarify your every question but alas I can’t make this claim. Moreover, certain idiosyncratic environmental issues?such as the number of Firefox extensions you have installed?might also contribute to some glitchy behavior.

After encountering some of these problems I upgraded my local version of the Dojo toolkit and now straddle both 0.2.2 and 0.3.1 in my incomplete, but growing Dojo knowledge. Little tweaks abound: I searched the web and found that the bootstrap1.js file sets the djConfig preventBackButtonFix value to ‘true’ by default. I was setting it to ‘false’ in my code but I changed the bootstrap1.js value as well and miraculously, a Firefox only error loading the page went away. The back button generally cooperates in Firefox but some of the updates of fields didn’t go smoothly for me in 0.3.1 using the same techniques that I used successfully with 0.2.2.

I loaded up my sample app in Opera but an info message there told me explicitly that Opera isn’t supported for back/forward button functionality but the rest of the code worked fine. Oddly, a colleague testing with the 0.2.2 version found Opera worked fine. The bottom line is that there are still some issues out there and while Dojo is under active development and headed in the right direction, you should expect some bumps in the road for now.

If you want to sort this data differently from the original presentation on the first page load you have two options. The first option is the old school way: submit the entire form back to the server to resort the data and reload the entire page. You probably guessed that the second option is to use AJAX. To implement the AJAX solution, mark up your page to include the ‘sortable’ list inside of a div block and use a button click or other client-side event, anywhere on the page, to invoke the AJAX call to resort the data as shown in Figure 2.


Figure 1. This is what you should see after the Dojo call is invoked to sort the list.
 
Figure 2. The list has been quickly reordered based on the “Ascending” selection in the drop-down, which invokes the AJAX call to re-sort the data without a server trip.

Here’s what such a div might look like if I were to code the HTML.

  • Dave Thomas
  • Ronald McDonald
  • George Washington

This div markup, however, is the generated HTML?to avoid having to repeatedly create this snippet I’d much prefer to use a Tile to make the whole block easy to reuse and less prone to error. Something like this would be preferable:

In the sample code there is a cached list of these users in a session attribute called “famousFolks.” This list will be resorted by the servlet that Dojo invokes using a standard Struts mapping to the URL (shown below).

 

The newly sorted list is passed to sortUpdateXml.jsp. This JSP contains a and the Tiles context pulls in the list of names as it creates the markup returned in the AJAX (Dojo) response.

Let’s fill in a little more functionality. The page that holds the AJAX call also includes a drop-down list field called sortBy that specifies an onchange event Javascript method call. The drop-down markup looks like the snippet below, but please check out the sample code for the full version.

When a new sort parameter is selected from the drop-down list the doSort( ) Javascript method defined in the or included from a Javascript (.js) resource file is invoked. With this bit of context set, let’s now take a look at the code for the Dojo call.

Dojo provides a varied and robust API that is generally speaking, intuitively packaged. With that said, it wasn’t immediately apparent to me that an AJAX call is set up using a method from the dojo.io package ?dojo.io.bind( ). (The ‘io’ must mean to and from the form. I would have preferred a .net package similar to Java’s.)

function doSort(sortTerm) {    dojo.io.bind( {        url: "famousPeopleSort.shtml",        content: {sortedBy: sortTerm},        method: "POST",        mimetype: "text/html",        load: function(type, value, evt) {            processReturnValue(value);        },                    backButton: function(){   //for maintaining Dojo back button stack            dojo.io.bind({                url: "famousPeopleSort.shtml",                content: {sortedBy: previousSortTerm},                method: "POST",                mimetype: "text/html",                load: function(type, value, evt) {                    resetDropDown(previousSortTerm);                    processAjaxResponse(value);                },                error: function(type, error) { alert("Error: " + error); }                   });        },        error: function(type, error) { alert("Error: " + error.reason); }   });

This method call sets the URL argument for an HTTP Post to the servlet mapped to famousPeopleSort.shtml in the struts-config.xml (shown earlier or see the sample code). The content term holds the sortTerm argument, passed by the drop-down list onchange event call to the function, and sets it as a request parameter of the Post. The method argument mimics the method attribute of the HTML form tag and the mimetype specifies the type of data expected in the AJAX response. The load argument defines a function to be invoked when the AJAX response is returned.

You also may have guessed from the above Javascript method that Dojo can maintain expected browser ‘back button’ behavior; it does so by creating its own call stack. This is useful because, of course, many users navigate backward using the back button. In such circumstances, Dojo-invoked actions would be lost without a full page reload and the missing behavior might be confusing. Instead, each Dojo call is stacked on top of the previous one. As the user clicks the ‘Back’ button, the topmost, bound (meaning it was invoked by the io.bind method) call is popped off the stack and consumed.

The stack is managed with the help of an HTML file (iframe_history.html) that resides in the same directory as dojo.js. It is worth mentioning that while I’ve had success implementing Dojo’s back button management features, other developers have reported some less pleasant experiences; if you encounter issues hopefully this anecdotal note will offer some comfort. 😉

While it is great to have some programmatic control of the back button, if your business stakeholders aren’t familiar with Dojo’s ‘back button’ behavior you ought to prototype/demo it for them before you get too far into development. AJAX calls create a very different navigation and page flow paradigm from what might be “expected.” Moreover, if something unknown (or that can’t be seen) is happening that makes your site appear unresponsive, then users are usually unhappy and your application isn’t likely to be successful. Therefore, you might want to consider adding a progress indicator or similar visual cue that starts up when the Dojo call is invoked and goes away when it is completed.

Before discussing how the returned data is processed I want to look at the response document that holds it. The response document for my famous personages sort is in XML format and acts as a container for the JSP tile referenced by the tile insert statement in the div described earlier.

<%@page contentType="text/xml" %><%@taglib prefix="tiles" uri="/WEB-INF/tiles.tld" %><%@taglib prefix="html" uri="/WEB-INF/struts-html.tld" %><%@taglib prefix="bean" uri="/WEB-INF/struts-bean.tld" %>                                                                               ]]>            

Because the tiles:insert is processed on the server, the Dojo call to the sorting action will rework the list and integrate it into the HTML created by the tile. When the AJAX call is made, this dynamically-generated HTML will be nested in the ajax-response XML element for processing by the Javascript function specified in the bind( ) method.

function processResponse(response) {           if (djConfig["isDebug"]) {                      dojo.debug("ajax response: " + response);           }           //if the XML element ?ajax-response? isn?t found then write out what was returned           if  (response.toLowerCase().indexOf("") < 0) {                      document.write(response);                      document.close();                      return;           }           //parse the AJAX XML response into a document.           var xmlDoc = dojo.dom.createDocumentFromText(response);           //refer to the XML response above ? the ?field? element is inside               //the response document.           var fields = xmlDoc.getElementsByTagName("field");           for (var i = 0; i < fields.length; i++) {                      var id = fields[i].getAttribute("id");                      var attribute = fields[i].getAttribute("attribute");                      var value = null;                 if (fields[i].hasChildNodes()) {                   for (var j=0; j

The processing of the response occurs during the parsing of the returned XML document. The code above finds the field element in the response and extracts its contents. It then replaces the div on the page with the specified #cdata-section value of the response. The replacement is an update to the DOM, of course, and the browser updates the display to reflect the change of content. This was the only cross browser parsing approach I could get working though I'm sure there are others out there.

Struts and Tiles have been key frameworks in enterprise Java development for years. AJAX and the Dojo toolkit are an excellent combination for using Struts and Tiles in a granular, service oriented manner that separates concerns and promotes the reuse of both code and display elements. While there is a learning curve to integrating these powerful frameworks, the payoff is worth the effort.

Share the Post:
Share on facebook
Share on twitter
Share on linkedin

Overview

The Latest

Top 5 B2B SaaS Marketing Agencies for 2023

In recent years, the software-as-a-service (SaaS) sector has experienced exponential growth as more and more companies choose cloud-based solutions. Any SaaS company hoping to stay ahead of the curve in this quickly changing industry needs to invest in effective marketing. So selecting the best marketing agency can mean the difference

technology leadership

Why the World Needs More Technology Leadership

As a fact, technology has touched every single aspect of our lives. And there are some technology giants in today’s world which have been frequently opined to have a strong influence on recent overall technological influence. Moreover, those tech giants have popular technology leaders leading the companies toward achieving greatness.

iOS app development

The Future of iOS App Development: Trends to Watch

When it launched in 2008, the Apple App Store only had 500 apps available. By the first quarter of 2022, the store had about 2.18 million iOS-exclusive apps. Average monthly app releases for the platform reached 34,000 in the first half of 2022, indicating rapid growth in iOS app development.