Skip to main content

Sprinkle Some AJAX Magic in Your Struts Web Application

{cs.r.title}









Contents
What is AJAX?
Life Before AJAX
AJAX 101
Using AJAX in Your Struts Application
Implementing the Solution
Existing Struts Application
Our First Struts AJAX Application
Don't Just Sit There
The AJAX Solution in More Detail
Making the AJAX Call to the Server
Updating the Web Page with the AJAX Response
New Flow of Control
Designing AJAX into Your Application
Conclusion
Resources

AJAX is the latest revolution in web development circles,
allowing rich dynamic interfaces deployed within a normal web
browser. Struts has been
one of the de facto standards for Java-Web development for a number
of years, with a large number of applications already deployed.
This article will show you how to combine the richness of an
AJAX user interface with your existing Struts applications.

This article shows a simple and elegant way to do this by
including a couple of lines of JavaScript on your JavaServer Pages
(JSPs). While we show how to reuse existing Struts actions, the
techniques are equally applicable to the Java-Web framework of your
choice. The method proposed will also allow a move to the next
version of Struts (Shale) or JavaServer Faces (JSF) in the
future.

What is AJAX?

AJAX stands for "Asynchronous JavaScript and XML." It is a
technique, rather than a framework (such as Struts). The reason for
the buzz around it is that it allows web pages to behave less
like flat documents and more like dynamic GUI apps that users might
expect from their desktop environments. AJAX techniques can be used
for all recent browsers (including Internet Explorer and
Netscape/Mozilla). It is already used by (among others) Microsoft
(for its Outlook web client) and Google (for 'http://maps.google.com'>Google Maps and 'http://mail.google.com'>Gmail).

Life Before AJAX

Most current Struts applications follow the standard "web page
as a flat document" structure. If you wanted to mimic the behavior
of GUI desktop apps (such as those built using Java Swing, Visual
Basic, or Delphi) you had two choices: you could either send all of the
information that might possibly required as part the web page with
(a lot of) JavaScript to handle the dynamic behavior (a slow and
not very enterprise-Java way to do things), or you could do
constant form submits back to the server (an effective, if somewhat
clunky, method). AJAX gives you the best of both worlds: dynamic
web pages, but with most of the application running in Java on your
web server.

AJAX 101

AJAX is similar to existing Dynamic HTML techniques, with the
addition of a "background" call to the server to get new/updated
information as required. The mechanics of AJAX have already been
covered in detail elsewhere--take a look at the "?page=3#resources">Resources section at the end of this article for some
good examples. The minimum you need to know
is:

  1. The XMLHttpRequest (or
    Microsoft.XMLHTTP ActiveX object if you are using
    Internet Explorer). These objects can be called from the JavaScript
    on your web page. They allow you to request content from your web
    server as a background call (i.e., the screen does not "go blank" as
    usually happens during a form submit).
  2. The content that the XMLHttpRequest and
    Microsoft.XMLHTTP objects return can be treated as
    either XML or plain text. JavaScript (on your web page) can then
    update the page with this new content as required.
  3. The whole process can be triggered by the usual JavaScript
    events: onclick, onchange,
    onblur, etc.

Using AJAX in Your Struts Application

The chances are that if you are reading this article, then you
are interested in AJAX's ability to create dynamic web interfaces
and would like to know how to add it to a Struts application. What
are your options if you want to do this?

  • Wait until the next version of Struts (Shale) incorporates AJAX
    techniques. For Struts developers starting a new application this
    is probably the best option. The downside is that this will
    probably require moving to JavaServer Faces--not a bad thing in
    itself, but this may entail fundamental changes if you have an existing
    application.
  • You could move to a new approach, like "https://dwr.dev.java.net/">Direct Web Remoting (DWR) or
    Ruby on Rails, which are
    specifically built for AJAX applications. While these are both very
    impressive frameworks, and are worth taking a look at if you wish
    to consider web development without Struts, this option would mean
    rewriting your entire application.
  • Add AJAX to your existing Struts application. Since AJAX is a
    technique, not a framework, it is straightforward to add it to
    Struts. For existing applications where stability (e.g., keeping
    existing libraries) is important, this option is recommended and is
    the one we explore in more detail.

Some other advantages of our preferred option are:

  1. It should not require any new libraries or server side code;
    only the Struts libraries and actions already in the application
    need be used.
  2. All of the parts of the solution--JavaScript, XML, Java and
    Struts--are already widely understood.
  3. The application can be migrated to AJAX piece by piece; we can
    identify those parts which will most benefit users, and then choose
    to upgrade them to dynamic AJAX behavior first.

Implementing the Solution

How do we actually implement our chosen solution? We start by
reminding ourselves how a "standard" (non-AJAX) Struts application
works. In this application, the normal flow of events is as
follows:

  1. The user requests a screen by clicking a hyperlink or form
    submit button.
  2. The web server runs the requested Struts Action,
    generating the web page.
  3. The browser displays the page.
  4. When the user presses Save, the information is posted
    to the server, where it's converted by the Struts framework to an
    ActionForm class containing the posted data.
  5. The Struts framework then calls the Struts
    Action that then processes the request (e.g., saves
    the data to a database).
  6. The page is rendered as per item 2, and the process starts
    again.

Existing Struts Application

A simple Struts application demonstrating this flow of events
can be downloaded here: 'http://sourceforge.net/project/showfiles.php?group_id=99476&package_id=158438'>
struts-non-ajax.zip
. This application, based on the sample
applications provided with Struts, either hides or displays blue
and green tables depending on the values entered by the user.
Figure 1 shows the screen on initial page load. Figure 2 shows the
screen after the user has entered values and pressed Submit.
Although simple, it is enough to demonstrate a Struts application
at work.

<br "Non-AJAX sample: Initial screen" />
Figure 1. Non-AJAX sample: Initial screen

<br "Non-AJAX sample: Values entered, Submit pressed" />
Figure 2. Non-AJAX sample: Values entered, Submit
pressed

The server-side code is as you would expect: a Struts
Action that forwards to the (same) JSP using the
values defined in struts-config.xml. Some other points to
note in this code sample are:

  • The struts-config.xml file is set up to redirect all requests
    to http://localhost:8080/struts-non-ajax/ (or
    the equivalent in your web server) to index.jsp.
  • index.jsp contains a Struts form with two text boxes
    (showBlue and showGreen). The page also contains
    tags, but as the values for these
    text boxes are initially blank, the content within them is not
    displayed.
  • The user enters values (true or false) and presses the Submit
    button, passing control (via the Struts Framework, reading
    struts-config.xml) to the SampleAction
    class.
  • SampleAction logs the values, and then forwards back
    to index.jsp. A more sophisticated Struts application would
    do more, such as saving to or retrieving from a database.
  • index.jsp now evaluates the request; if showBlue or
    showGreen are true, the tables will be displayed.

There is nothing "wrong" with this application. After all,
similar Struts projects have been deployed for years. But how do we
to add dynamic behavior to this application, without adding
complex JavaScript or continual form submits?







Our First Struts AJAX Application

Take a look at the Figures 3 and 4 below. At first glance, they
seem similar to our previous ones. The difference is that after
then screen loads (Figure 3) and the values in the textboxes are
changed, the screen automatically updates without the
screen going blank, giving the result as per Figure 4. The normal
Submit button is also still there, should you choose to use
it.

<br "AJAX Sample after Page Load" />
Figure 3. AJAX sample after page load

<br "AJAX sample after AJAX call" />
Figure 4. AJAX sample after AJAX call

Adding this AJAX behavior is surprisingly easy. The server-side
code is the same as usual: a Struts ActionForm to hold
the data, and a Struts Action that performs the tasks
required (e.g., database access) and then forwards to the
appropriate JSP to display the result.

Don't Just Sit There

If you wish to stop reading here (and skip the explanation of how
this works) then here is all you need to do to convert your Struts
application to a Struts-AJAX application in a similar manner:

  1. Include the Ajax.js JavaScript file on your web page
    (this file is part of the 'http://sourceforge.net/project/showfiles.php?group_id=99476&package_id=158438'>
    struts-ajax.zip
    sample file). Ajax.js contains all of the
    JavaScript functions necessary to send and receive AJAX calls.
  2. Ensure the parts of the web page that you wish to update during
    AJAX calls are surrounded by tags, giving
    each an id.
  3. When something happens that should update the page (e.g., the
    onchange() method of a textbox), call the
    retrieveURL() function, passing in the URL to the
    Struts Action that will do the necessary server-side
    processing.
  4. For page display/update, the easiest option is for the Struts
    Action to forward back to the same JSP. In our
    sample, we trigger the AJAX call in the onchange()
    method of the showGreen/showBlue textboxes.

The JavaScript function retrieveURL() calls Struts
on the server (via the URL provided), takes the JSP response, and
updates the web page being displayed, where the
tags on the existing web page match those
on the newly returned JSP. Simple!

The AJAX Solution in More Detail

When we converted the previous sample into an AJAX-Struts
application we made three changes:

  1. Added a JavaScript function to do the "behind the scenes" AJAX
    call to the server.
  2. Added JavaScript code to receive the server response and update
    the web page.
  3. Added tags to the JSP page, which mark
    sections that will be updated during AJAX calls.

We will look at each of these in more detail.

Making the AJAX Call to the Server

There are two functions (listed below) that are used to call the
server.

  • The retrieveURL() function takes a parameter of
    the URL of the server and the name of the Struts form. The URL will
    be called using AJAX and the values of the form passed to the
    server.
  • getFormAsString() is a function that converts the
    values on the form named in retrieveURL() into a
    query string suitable for posting to Struts on the server.

To use, simply add the retrieveURL() function to
the onclick()/onChange() method of the
event you wish to trigger the screen update.

There are some interesting items going on in both methods.

Within the retrieveURL() method, the line
req.onreadystatechange = processStateChange (note: no
brackets) tells the browser to call the
processStateChange() method (which we talk through
later in this article) once the server sends back its response.
This method (now standard in AJAX) also determines whether it
should use the Internet Explorer (ActiveX) or Netscape/Mozilla
(XmlHttpRequest) object to ensure cross-browser
compatibility.

The getFormAsString() method converts the HTML form
into a string to be appended to the URL (which allows us to do a
HTTP GET request). This string is escaped (spaces are converted to
%20, etc.) and is in a format that Struts can use to
populate an ActionForm (without Struts being aware of
the special AJAX nature of the request). Note that while we use a
HTTP GET in this sample, it would be equally possible to use a HTTP
POST by looping in a similar manner and adding the form fields to
the request.

[prettify]
function retrieveURL(url,nameOfFormToPost) {
    
  //convert the url to a string
  url=url+getFormAsString(nameOfFormToPost);
    
  //Do the AJAX call
  if (window.XMLHttpRequest) { 
     
    // Non-IE browsers
    req = new XMLHttpRequest();
    req.onreadystatechange = processStateChange;
    try {
          req.open("GET", url, true); 
    } catch (e) {
      alert("Server Communication Problem\n"+e);
    }
    req.send(null);
  } else if (window.ActiveXObject) {
    // IE
   
    req = new ActiveXObject("Microsoft.XMLHTTP");
    if (req) {
      req.onreadystatechange=processStateChange;
      req.open("GET", url, true);
      req.send();
    }
  }
}
[/prettify]

getFormAsString() is a "private" method used by the
retrieveURL() method.

[prettify]
function getFormAsString(formName){
        
  //Setup the return String
  returnString ="";
        
  //Get the form values
  formElements=document.forms[formName].elements;
        
  //loop through the array, building up the url
  //in the format '/strutsaction.do&name=value'
 
  for(var i=formElements.length-1;i>=0; --i ){
        //we escape (encode) each value
        returnString+="&" 
        +escape(formElements[i].name)+"=" 
        +escape(formElements[i].value);
 }
        
 //return the values
 return returnString; 
}
  
[/prettify]







Updating the Web Page with the AJAX Response

So far, we have looked at the JavaScript to do the AJAX call
(listed above) and the Struts Action,
ActionForm, and JSP (mostly the same, with
the addition of tags). To complete our
understanding of the Struts-AJAX project, we need to look at the
three JavaScript functions that are responsible for updating the
current web page when the results from the server are received.

  • processStateChange(): The method name that we set
    before making the AJAX call. This method is called by the
    XMLHttpRequest/Microsoft.XMLHTTP object
    once the server has completed sending back its response.
  • splitTextIntoSpan(): Loops through the response,
    picking out an array of
    id="someName">NewContent
    elements.
  • replaceExistingWithNewHtml(): Loops through this
    array of span elements, searching for
    elements in the existing
    page with 'someName' and replacing them with the new
    content from the server. Note that we get the returned content via
    req.responseText for robustness (since it allows us to
    manipulate any text response), rather than
    req.responseXml (which is more powerful, but requires
    that you return valid XHTML or XML).
function processStateChange() {
 
  if (req.readyState == 4) { // Complete
    if (req.status == 200) { // OK response
       
    //Split the text response into Span elements
    spanElements =
        splitTextIntoSpan(req.responseText);
   
    //Use these span elements to update the page
    replaceExistingWithNewHtml(spanElements);
   
    } else {
      alert("Problem with server response:\n "
        + req.statusText);
    }
  }
}
replaceExistingWithNewHtml() is a "private" method
used by the processStateChange() method.

  
function replaceExistingWithNewHtml
        (newTextElements){

  //loop through newTextElements
  for(var i=newTextElements.length-1;i>=0;--i){
 
    //check that this begins with     if(newTextElements[i].
        indexOf("-1){
                       
          //get the span name - sits
      // between the 1st and 2nd quote mark
      //Make sure your spans are in the format
      //NewContent
          startNamePos=newTextElements[i].
              indexOf('"')+1;
      endNamePos=newTextElements[i].
              indexOf('"',startNamePos);
      name=newTextElements[i].
              substring(startNamePos,endNamePos);
                       
      //get the content - everything
      // after the first > mark
      startContentPos=newTextElements[i].
               indexOf('>')+1;
      content=newTextElements[i].
               substring(startContentPos);
                       
     //Now update the existing Document
     // with this element, checking that
     // this element exists in the document
     if(document.getElementById(name)){
                document.getElementById(name).
                innerHTML = content;
     }
  }
}
splitTextIntoSpan() is a "private" method used by
the processStateChange() method.

function splitTextIntoSpan(textToSplit){

  //Split the document
  returnElements=textToSplit.
            split("")
       
  //Process each of the elements       
  for(var i=returnElements.length-1;i>=0;--i){
               
    //Remove everything before the 1st span
    spanPos = returnElements[i].
             indexOf("               
    //if we find a match, take out
    //everything before the span
    if(spanPos>0){
          subString=returnElements[i].
              substring(spanPos);
          returnElements[i]=subString;
    }
  }
  return returnElements;
}

New Flow of Control

By adding the above JavaScript code to our application, the
following steps now happen on the server and on the browser.

  1. The page loads as per a normal Struts application.
  2. The user changes a textbox value, triggering an
    onChange() event, which calls the
    retrieveURL() JavaScript function.
  3. This JavaScript function makes a (background) call to the
    Struts Action on the server, passing in all of the form variables in a
    way that Struts will understand.
  4. This JavaScript function also sets the name of a second
    JavaScript function, which will be called when the server response
    is finished. In this case, it is set to the
    processStateChange() method.
  5. As expected, when the server response is finished, the
    processStateChange() method is called.
  6. The JavaScript loops through all of the
    elements in the (new) server response.
    Where it finds a in the existing page
    with the same name, it updates it with the new content.

Designing AJAX into Your Application

The JavaScript outlined above can cope with the way Struts is
used in most applications, including those that are much more
complex than our simple example. However, you may find that
following the points below makes it easier to write and use your
code:

  • To avoid duplicated code, it can often be better to use the
    same Struts Action and JSP for the initial request
    (i.e., show full page) and the AJAX (update part of page)
    requests.
  • Within the common Action (controller) class, decide which
    sections of the JSP page (all of the JSP or only part of it) need to be sent to the
    browser. By setting flags in either the web server
    session or ActionForm, the JSP page knows
    which sections need to be rendered.
  • Within the JSP, use Struts or
    JSTL tags to decide if we need to render a section of HTML or
    not.

An updated version of this project, with AJAX enabled, can be
downloaded here: 'http://sourceforge.net/project/showfiles.php?group_id=99476&package_id=158438'>
struts-Ajax.zip

Conclusion

AJAX techniques promise to completely revolutionize how we build
and use web applications. This article showed a simple technique to
add AJAX behavior to existing Struts applications. It allows us to
reuse our existing investment, not only in code but also in
developer skills. As a nice by-product, it also allows us to write
cleaner, more reusable, Java Struts applications.

Resources

width="1" height="1" border="0" alt=" " />
Related Topics >> JSP   |   Struts   |   Web Design   |