You are on page 1of 13

Ajax support in struts 2.

0
by Jesintha Priyadarshini L
09/06/2007

Introduction

Ajax or Asynchronous JavaScript and XML was introduced by Jesse James Garrett in
2005. He is called the “Father of Ajax” .Ajax is a collection of concepts and technologies
that allows richer and more interactive user interaction with the web applications. The
Ajax engine allows the user’s interaction with the application to happen asynchronously
— independent of communication with the server. So the user is never staring at a blank
browser window and an hourglass icon, waiting around for the server to do something.

Who is using AJAX

The most popular and the biggest user of AJAX is Google. Orkut, Gmail, the latest beta
version of Google Groups, Google Suggest, and Google Maps — are Ajax applications
Google mail, Google calendar and Google home page are some examples. In your
Google mailbox the “loading” that is displayed in the top right corner is using these Ajax
technologies. The new Yahoo homepage too uses some of these technologies. Another
cool Ajax implemented website would be www.pageflakes.com Others are following
suit: many of the features that people love in Flickr depend on Ajax, and Amazon’s
A9.com search engine applies similar techniques.

The Back Screen of Ajax

In traditional WebPages, the pages will be reloaded for each and every request. But in
most of the cases only a part of the page will be processed. Hence such a page reload is
unnecessary. Thus the usage of Ajax plays a efficient role. In the WebPages, that are
using Ajax, only the part of the page that has to be processed will be transferred to
the web server and the processed data will be loaded in the page without a page
reload.

JAX internals

AJAX is not a single technology as mentioned earlier. It is important to remember that


AJAX is not Java or .NET dependent.
Whatever be your back end code, you can use AJAX to communicate with it. People
prefer AJAX for the high speed with which it works. It does it with three basic ways

1. Better utilization of browser cache


2. Batching up of network requests in a single packet to reduce network latency
issues
3. Decreasing the workload on the server by not requiring it to process the entire
page

Where can we use AJAX

Forms:
Web based forms are slow. AJAX can definitely improve the performance of
web-based forms
User Communication:
User communications like chat pages, voting’s and ratings can be done efficiently
using AJAX
News:
RSS feed is another popular concept where AJAX can be used
Data Manipulation:
This includes some sort of filtering data, selecting names from one combo box to
another, sorting data, invoking the suggest criteria or a hint

Defining Ajax

As we have seen an introduction to AJAX, let us try to define it. Ajax isn’t a technology.
It’s really several technologies, each flourishing in its own right, coming together in
powerful new ways. Ajax incorporates:

o Standards-based presentation using XHTML and CSS;


o Dynamic display and interaction using the Document Object Model;
o Data interchange and manipulation using XML and XSLT;
o Asynchronous data retrieval using XMLHttpRequest;

And JavaScript binding everything together. So, how does AJAX does this sending
request and getting response from the backend server??
Using the XML Http Request object.

XML Http Request object

The XML HttpRequest was introduced by Microsoft in Internet Explorer 5.0. Recently,
Mozilla and apple have included support for this in their web browsers (Firefox and
Safari).This object is the fundamental basis for Ajax. Microsoft implementation is
different from that of other web browsers, so when you create this object in your code,
you need to do a typical browser check.
For Internet Explorer, we can create this object using,
Var req = new ActiveXObject(“Microsoft.XMLHTTP”);
For firefox and safari,
Var req = new XMLHttpRequest();
Struts and Ajax in Action

As we have seen enough of the theory behind the working of Ajax in struts let us see an
example. Simple example is loading a drop down depending on the selected item in
another drop down.
We need to populate the characters in a “showcharacters” dropdown when a particular
TV Show is selected in the “showTVShow” drop down using AJAX. Let us see the Ajax
request response cycle for this scenario.

Fig 1.1 Ajax Request Response Cycle

Step 1: Create a jsp page (“tvshow.jsp”)

Let us take three TV shows which I like.”Lisse Maguire”,” That’s so Raven” and
“Dhoom Machallo Dhoom”. We need to populate the characters dropdown as and when
the TV Show dropdown value changes , so we decide to call the javascript in the
“onchange()” of the select box.

<html:form action="showCharacters.do">
TV Show:
<html:select property="TVShowSelect" onchange="retrieveURL('
showCharacters.do?tvShow=' + this.value);">
<html:option value="Lissie Maguire"> Lissie Maguire
</html:option>
<html:option value="That’s so Raven"> That’s so Raven
</html:option>
<html:option value="Dhoom machale"> Dhoom machale </html:option>
</html:select>
<br>
Characters: <span id="characters"></span>
</html:form>

Here we are sending a URL to the Java script function.

“’ showCharacters.do?tvShow=' + this.value”

We are appending the selected item with the URL as a query string. We
can also just send the Url and append the form contents in the java
script.

Step:2 Making the AJAX Call to the Server

In the java script we need to create a XML HttpRequest object

function retrieveURL(url)
{
if (window.XMLHttpRequest)
{
// Non-IE browsers
req = new XMLHttpRequest();
req.onreadystatechange = processStateChange;
try {
req.open("GET", url, true);
} catch (e) {
alert(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();
}
}
}
Within the retrieveURL() method, the line req.onreadystatechange =
processStateChange (note: no brackets) tells the browser to call the
processStateChange() method 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.
Now when the XMLHttpRequest object is created , we ask the browser to
call the processstatechange method when we get the response from the
server.

Step 3: Configure action path in struts-config

This is the same old struts functioning.


“’showCharacters.do” is configured in the struts-config.xml
struts-config.xml

<action path="/showCharacters " type="ShowTVAction" validate="false" >


<forward name="success" path="/pages/showCharacters.jsp" />
</action>

Step 4: Write the action class

The action class has to get the value selected in the TVShow dropdown and Get the
appropriate list of characters using the function getCharacters(String tvShow) .

public class ShowTVAction extends Action


{

public ActionForward execute(ActionMapping mapping, ActionForm


inForm, HttpServletRequest request, HttpServletResponse response)
throws Exception
{

// Get a list of characters associated with the select TV show


String tvShow = (String) request.getParameter("tvShow");
if (tvShow == null)
{
tvShow = "";
}
ArrayList characters = getCharacters(tvShow);
request.getSession().setAttribute("characters", characters);
response.setContentType("text/html");
return mapping.findForward("success");
} // End execute()

// This method returns a list of characters for a given TV show. If


no TV
// show is selected, i.e., initial page view, am empty ArrayList is
returned.

private ArrayList getCharacters(String tvShow)


{
ArrayList al = new ArrayList();

if (tvShow.equalsIgnoreCase("Lissie Mcguire"))
{
al.add("Lizzie Mcguire");
al.add("Mathew Mcguire");
al.add("Miranda");
al.add("Gordon");
}

if (tvShow.equalsIgnoreCase("That’s so Raven "))


{
al.add("Raven");
al.add("Chelse”);
al.add("Orlanda");
al.add("Victor Backstor");
al.add("Cory Backstor");
}

if (tvShow.equalsIgnoreCase("Dhoom machale "))


{
al.add("Priyanka");
al.add("Koyel");
al.add("Nehal");
al.add("Aadhiraj");
al.add("Maleni");
}

return al;

} // End getCharacters()

} // End class

Then it sets the Appropriate characters in the session and returns the keyword “success”
Thus the control passes to showCharacters.jsp

Step 5: Write the contents you need to reload in the characters drop
down (“ShowCharacters.jsp”)

In the showCharacters.jsp we load the contents of the characters drop down by taking
their values from the session.
Remember to add the tag libraries and surround the code with a form tag.

ShowCharacters.jsp

<html:select property="TVShowSelect">
<logic:present name="characters">
<%ArrayList ch = (ArrayList)
request.getSession().getAttribute("characters");
String[] s = new String[ch.size()];
ch.toArray(s);
for(int i=0;i<s.length;i++)
{%>
<html:option value ="<%=s[i] %>"
></html:option>
<%} %>
</logic:present>
</html:select>

Thus the showCharacters.jsp is the response from the Back end server. Once the response
form the server is got by the browser. It calls the processStateChange() method

Step 6: 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 following
JavaScript function that is 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. The
XMLHttpRequest/Microsoft.XMLHTTP object calls this method once the server has
completed sending back its response.

function processStateChange()
{
if (req.readyState == 4)
{ // Complete
if (req.status == 200)
{ // OK response

document.getElementById("characters").innerHTML =
req.responseText;
}
else
{
alert("Problem: " + req.statusText);
}
}
}

Here readystate is checked .If it is equal to 4 , it means the response is completely


received and the status of the response is checked to 200.
If everything fit in, the response is set as the innerHTML of the span “characters”. We
can also give the response to a div.

Thus we have done a asynchronous call to the back end and got the response and set it to
a span element. Only the contents of the span have been reloaded while the rest of the
page remained there.
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 dropdown 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
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 sets the response to a span in the page

New Features in Struts 2.0 for AJAX

One of the useful enhancements in Struts 2.0 is the introduction of AJAX Theme

The Ajax theme extends the xhtml theme with AJAX features. The theme uses the
popular DOJO AJAX/JavaScript toolkit. The new AJAX features include:

• AJAX Client Side Validation


• Remote form submission support (works with the submit tag as well)
• An advanced div template that provides dynamic reloading of partial HTML
• An advanced a template that provides the ability to load and evaluate JavaScript
remotely
• An AJAX-only tabbed Panel implementation
• A rich pub-sub event model
• Interactive auto complete tag

The framework provides a set of tags to help you ajaxify your applications, on Dojo.

To use the Ajax tags you need to set the "theme" attribute to "Ajax".Use the head tag to
configure the page for the Ajax theme.

URL

The "href" attribute must contain a url built with the URL tag
Example:
<s:url id="ajaxTest" value="/AjaxTest.action" />
<s:div theme="ajax" href="%{ajaxTest}">
Initial Content
</s:div>

Set the "debug" attribute of the head tag to "true" to display debug information on the
bottom of the page

Indicators

Use indicators to notify the user that a request is in progress. The indicator should be
hidden when the page is loaded.
This indicator is an image:

<img style="display:none" src="$


{pageContext.request.contextPath}/images/indicator.gif"
alt="Loading..."/>

Dynamic Div

The div tag is a content area that can load its content asynchronously. The div tag can be
forced to reload its content using topics. To define the topics that will trigger the refresh
of the panel, use the "listenTopics" attribute. This tag will load its content when the page
is loaded, unless "autoStart" is set to "false".
While Dojo supports crossdomain XHR using IFrames, the S2 Ajax tags do not (yet)

This div will refresh every time the topics "/refresh0" or "/refresh1" are published:

<s:url id="ajaxTest" value="/AjaxTest.action" />


<s:div theme="ajax" href="%{ajaxTest}"
listenTopics="/refresh0,/refresh1"/>
to publish a topic use.
dojo.event.topic.publish("/refresh”);

Retrieve Remote Data

The simplest way to use the div tag is to provide an href attribute. For example

<s:div theme="ajax" id="weather" delay="2000" updateFreq="60000"


href="http://www.weather.com/weather?zip=97239"/>

What this does after the HTML page is completely loaded; the specified URL will be
retrieved asynchronously in the browser. The entire contents returned by that URL will
be injected in to the div and will update every minute after a two second delay:
Include the attribute errorText in case the URL is not loaded

errorText="Unable to contact weather server"


Submit

The submit tag can be used to update the content of its "targets" attribute with text
returned from the asynchronous request. "targets" is a comma-delimited list of element
ids. The "targets" attribute is optional.

Regular submit button that will update the content of div1:

<div id="div1">Div 1</div>


<s:url id="ajaxTest" value="/AjaxTest.action" />
<s:submit type="submit" theme="ajax" value="submit"
targets="div1" href="%{ajaxTest}"/>

For using Submit button using an image add the attribute src

src="${pageContext.request.contextPath}/images/struts-rocks.gif"

If the submit button is used inside a form (href is not required on this case), the form will
be submitted asynchronously using

<s:submit type="button" theme="ajax" label="Update Content"/>


<s:form id="form" action="AjaxTest">

A submit button can be used to submit a form, even if it is outside the form, using
"formId", "formFilter" and "href". Note that in this case "href" is required.

<s:form id="form1">
<input type="textbox" name="data">
</s:form>

<s:url id="ajaxTest" value="/AjaxTest.action" />

<s:submit type="submit" theme="ajax" href="%{ajaxTest}"


formId="form1"/>

Anchor

The anchor tag, like the submit tag; can be used to update the content of its "targets"
attribute with text returned from the asynchronous request. "Targets" is a comma-
delimited list of element ids. The "targets" attribute is optional.

This anchor will update the content of div1 and div2 with text returned form
"/AjaxTest.action"

<div id="div1">Div 1</div>


<div id="div2">Div 2</div>
<s:url id="ajaxTest" value="/AjaxTest.action" />
<s:a theme="ajax" href="%{ajaxTest}" targets="dev1,dev2">Update
divs</s:a>
If the anchor tag is used inside a form (href is not required on this case), the form will be
submitted asynchronously:

<s:form id="form" action="AjaxTest">


<input type="textbox" name="data">
<s:a theme="ajax">Submit form</s:a>
</s:form>
Using the anchor tag to submit a form:
<s:form id="form1">
<input type="textbox" name="data">
</s:form>

<s:url id="ajaxTest" value="/AjaxTest.action" />


<s:a theme="ajax" href="%{ajaxTest}" formId="form1">Submit
form</s:a>

AJAX Client Side Validation

• Ajax Validation requires DWR servlet being setup, Dojo and the Ajax theme
being used.
• In the Ajax theme, DWR is used for normal validation while Dojo handles
everything else (widgets, XHR, browser JS events etc.)
• In order for validation to function properly it is advised to use standard Struts
Tags

Setup DWR

DWR could be setup by having the following dwr configuration (dwr.xml) at /WEB-INF/
directory. If it needs to be in other places.

<!DOCTYPE dwr PUBLIC


"-//GetAhead Limited//DTD Direct Web Remoting 1.0//EN"
"http://www.getahead.ltd.uk/dwr/dwr10.dtd">

<dwr>
<allow>
<create creator="new" javascript="validator">
<param name="class"
value="org.apache.struts2.validators.DWRValidator"/>
</create>
<convert converter="bean"
match="com.opensymphony.xwork2.ValidationAwareSupport"/>
</allow>

<signatures>
<![CDATA[
import java.util.Map;
import
org.apache.struts2.validators.DWRValidator;

DWRValidator.doPost(String, String, Map<String,


String>);
]]>
</signatures>
</dwr>

A DWRServlet need to be registered with the web application as well. The following
shows a typical web.xml with DWRSerlvet.

<servlet>
<servlet-name>dwr</servlet-name>
<servlet-
class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>true</param-value>
</init-param>
</servlet>

<!-- JavaServer Faces Servlet Configuration, not used directly


-->
<servlet>
<servlet-name>faces</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-
class>
<load-on-startup>1</load-on-startup>
</servlet>

<!-- JavaServer Faces Servlet Mapping, not called


directly -->
<servlet-mapping>
<servlet-name>faces</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>

<servlet-mapping>
<servlet-name>dwr</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>

Add a form attribute

Add the attribute validate to the <s:form >. The validate="true" option is set for the
<s:form /> tag to enable onblur-triggered validation

<html>
<head>
<title>Validation - Basic</title>
<s:head theme="ajax"/>
</head>

<body>

<s:form method="post" validate="true" theme="ajax">


<s:textfield label="Name" name="name"/>
<s:textfield label="Age" name="age"/>
<s:textfield label="Favorite color" name="answer"/>
<s:submit/>
</s:form>

</body>
</html>

Now as usual have a form bean for this form with getters and setters and constructors,
and configure the validation.xml for required fields

<field name="name">
<field-validator type="requiredstring">
<message>You must enter a name</message>
</field-validator>
</field>
<field name="age">
<field-validator type="int">
<param name="min">13</param>
<param name="max">19</param>
<message>Only people ages 13 to 19 may
take this quiz</message>
</field-validator>
</field>

Conclusion

This is a simple introduction to Ajax.Start implementing it and you will find it simple,
easy and attractive. One can use it to do many different things. It all accounts your
creativity. It is a good approach in many cases, but will not be appropriate in others. If
reaching the maximum possible audience is your goal, you would want to stay away from
this. If a user disabling scripting in their browser might be a concern (and your site
wouldn’t be any good without it), this probably isn’t a good answer either. There are
other reasons to stay away from it in some situations, but the bottom line is treat it like
any other tool in your toolbox: it will be right for some jobs, maybe "not so" for others.

You might also like