web     learntechnology.net
Struts Ajax (Using APT Tags)
[ print format ]

( Note: 11/14/07 If doing any new ajax development, I'd use ExtJS and/or JQuery )

struts-ajax-crud.zip source code
struts-ajax-crud.war

Introduction
This Struts lesson uses the Java Web Parts library to aid us in our Ajax functionality. This application is basically the struts-crud application with some ajax added and a new managerId property. When the user selects a department from the department dropdown, the manager drop down options are updated via Ajax and the user selects an appropriate manager. This is a much cleaner approach than having to refresh the entire JSP page on an onchange event or having to store every possible onchange option within the JSP on the first load of the form.

Even though I use Struts for the framework, the topics discussed here can be applied to any JSP application or Java web framework.

Thanks to Frank Zammetti for starting up and leading the Java Web Parts project.

Requirements
This application requires an application server that implements the Servlet 2.4 and JavaServer Pages 2.0 specifications. The examples should all work on Tomcat 5.x (Discussed in next section). Please do not e-mail about getting your application to run on a server other than Tomcat. The source code (and an Ant build file) is provided for all the lessons so you should be able to build a war from the source and run it on you application server of choice.
JWP Jars
For the Struts application, you'll need the typical jars as discussed in previous lessons. The two Java Web Parts jars are new to this application:
  • javawebparts-core.jar
  • javawebparts-ajaxparts.jar
The jars are included in the source and war for this lesson or you can of course get the latest jars by downloading the latest Java Web Parts.
Ajax in general
Keeping in line with the other lessons presented here, this isn't a primer on what Ajax is about. Ajax isn't even really a 'new' technology (well at least in regard to using it with Inernet Explorer:). At the time of writing this lesson, I'd consider myself just a beginner in regard to using Ajax. You can Google to find out more about Ajax, but I found this articlea great introduction.
Configuring our web.xml
In our web.xml file the following is added to provide our Ajax functionality:

<!-- This parameter is needed to initialize AjaxTags.  It points to the -->
<!-- context-relative confiruation file. -->
<context-param>
    <param-name>ajaxTagsConfig</param-name>
    <param-value>/WEB-INF/ajax-config.xml</param-value>
</context-param>
 
<!-- This servlet will be called by our Ajax component -->
<!-- It will write out the new select options -->
<servlet>
    <servlet-name>ManagerServlet</servlet-name>
    <servlet-class>net.reumann.demo.servlet.ManagerServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>ManagerServlet</servlet-name>
    <url-pattern>/managerServlet</url-pattern>
</servlet-mapping>
employeeForm.jsp
When the user selects a department from the select options, we want to use AJax (XMLHttpRequest()) to make sure the 'managers' div is updated with the new select options. Since I'm using Struts, I'm using the Struts html:select and html:option tags, but just imagine those are standard html form tags. (In fact, when we look at the ManagerServlet, you'll see that the ManagerSerlvet does simply write out the html standard form select and options tags.)

The first thing we need to remember is to include our taglib reference at the top of our JSP:

<%@ taglib prefix="ajax" uri="javawebparts/ajaxparts/taglib" %>

We also need to make sure we include an Ajax enabled tag somewhere at the end of our JSP. This tag will be responsible for generating javascript based off our form elements. The best place for this tag is right before the closing body tag (This way if you use a decorating framework lke Sitemesh the resulting generated code will be sure to be carried over to the decorated content).

<ajax:enable />
</body>

The relevant portion of our JSP form with our two select box areas:

<td class="tdLabel">
    <fmt:message key="label.department"/>:
</td>
<td>
    <html:select property="departmentId">
        <c:forEach var="dept" items="${departments}">
            <html:option value="${dept.departmentId}">
                <c:out value="${dept.name}"/>
            </html:option>
        </c:forEach>
    </html:select><ajax:event ajaxRef="employeeForm/showManagers"/>
</td>
<td style="font-weight:bold;">
    <fmt:message key="label.manager"/>:
</td>
<td>
    <div id="managers">
        <html:select property="managerId">
            <c:forEach var="manager" items="${managers}">
                <html:option value="${manager.managerId}">
                    <c:out value="${manager.name}"/>
                </html:option>
            </c:forEach>
        </html:select>
    <div>
</td>
The key above is the use of the ajax:event tag. How the ajax:event is implemented is based on the ajaxRef attribute which looks in our ajax-config.xml file for its behavior. The ajax-config.xml is shown in the next section.
ajax_config.xml

<ajaxConfig>
    <group ajaxRef="employeeForm">
        <element ajaxRef="showManagers">
            <event type="onchange">
                <requestHandler type="std:QueryString" target="/managerServlet">
                    <parameter>departmentIdForAjax=departmentId</parameter>
                </requestHandler>
                <responseHandler type="std:InnerHTML">
                    <parameter>managers</parameter>
                </responseHandler>
            </event>
        </element>
    </group>
</ajaxConfig>
ManagerServlet

public void doPost(HttpServletRequest request, HttpServletResponse response)
                     throws ServletException, IOException {

    logger.debug("In doPost of MangerServlet");
    String departmentId = request.getParameter("departmentIdForAjax");
    ManagerService service = new ManagerDaoService();
    List managers = service.getManagers(Integer.parseInt(departmentId));

    PrintWriter out = response.getWriter();
    out.println("<select name='managerId'>\n");

    if (managers != null) {
      Iterator managerIter = managers.iterator();
      while( managerIter.hasNext() ) {
        Manager manager = (Manager)managerIter.next();
        out.println("  <option value='"+manager.getManagerId()+"'>" +
        manager.getName() + "</option>\n");
      }
    }
    out.println("</select>\n");
    out.flush();
    out.close();
}
Code and Lesson - Rick Reumann