As a diligent Java EE developer, you've probably read numerous how-to articles on Ajax and are excited about the possible improvements it can bring to your applications. But how will Ajax's asynchronous communication-based pattern fit into your Java EE applications? This article helps you answer this question by examining the impact of introducing Ajax on the design, development, performance, and testing of a Java EE application. My purpose isn't to discourage the use of Ajax or to imply that the problems you might encounter are inherent to Ajax technology. Rather, it's to help you plan for and thereby mitigate issues to make your use of Ajax effective and unintrusive.
For quite some time now, the Java community has been diligent in applying good design patterns to Web-related application development. One of the most widely used patterns is Model-View-Controller (MVC). Several open source frameworks, such as Apache Struts, are based on this design pattern/architecture (see Resources). MVC's several advantages include separation of concerns and decreased redundant code.
Separation of concerns lets each developer in a given application-development project focus on a specific role in by using prenegotiated interfaces throughout the application architecture. For example, model-layer developers focus on technologies such as JDBC, Enterprise JavaBeans (EJB) components, or Java classes that interface with underlying data-persistence technologies. View-layer developers focus on JavaServer Pages (JSP) technology, tag libraries, and other presentation-related technologies. The controller layer separates and mediates the model and view, routing incoming requests to back-end persistence calls while maintaining clear separation of concerns. Figure 1 illustrates the MVC architecture:
Figure 1. MVC architecture
Table 1. MVC without Ajax: Amount of code related to a typical view-layer sequence
|Before invoking synchronous request||Scriptlet code required in preparing for form submission.||No.|
|Invoking of synchronous request||Form submission is invoked by button or link invocation; DOM element values are automatically set to ||No: All that is required is a way to invoke page submission.|
|Handling response to synchronous request||After server-side code finishes execution, typically, an object is sent back to the JSP (via ||Yes: Minimal scriptlets.|
Contrast Table 1 with Table 2, which describes the MVC view layer with Ajax, again assuming that the controller layer is implemented by servlets and the view layer by JSP technology.
Table 2. MVC with Ajax: Amount of code related to a typical view-layer sequence
You can see that the amount of scripting code in the view layer increases with the use of Ajax, causing three significant drawbacks:
- The design breaks the separation of role concerns.
- The design reintroduces monolithic JSPs (the Model 1 approach: a sea of HTML, CSS code, images, and scripting code), an antipattern that is extremely difficult to read and maintain (see Resources).
You have several options for avoiding or at least mitigating these design drawbacks:
- Design with reuse in mind: Unfortunately, scripting code specific to Ajax support is often difficult to avoid. Plan and design the scripting code so that you get maximum reuse from it.
- Employ a client-side MVC approach: You can incorporate a client-side MVC approach, as detailed Ajax in Action by Dave Crane et al. (see Resources). This approach promotes separation of concerns but adds complexity, so you should use it only with careful consideration.
- Use an Ajax framework: Several open source Ajax frameworks, such as Direct Web Remoting (DWR) (see Resources), do a good job of integrating the Ajax pattern into a Java EE application with minimal coding.
- Reassess the design's validity: Essentially, Ajax provides Web applications with desktop-application attributes. If most of the client-side interactions in a given Web application leverage Ajax, that application might well be better designed as a desktop application.
When you use Ajax in Java Web development, it is important to understand fully the difference between the synchronous and asynchronous communication models (see Resources). Lack of support for the asynchronous communication model can have an impact on client-side development, integration with Web frameworks, use of tag libraries, IDE use, and threading behavior.
In the synchronous request/response communication model, the browser (as opposed to the Web server, application server, or Web application) always initiates requests (via the Web user). In turn, the Web server, application server, or Web application responds to the incoming requests. During the processing of a synchronous request/response pair, the user can't continue to use the browser.
Figure 2 is a sequence diagram that illustrates traditional Web applications' synchronous communication model. Notice that in the server's lifeline, data submission from the client and the server-side processing are tightly coupled.
Figure 2. Synchronous communication sequence
In the asynchronous request/response communication model, the communication between the browser (via the Web user) to the Web server, application server, or Web application (and vice versa) is decoupled. During the processing of an asynchronous request/response pair, a Web user can continue to use the browser while the current asynchronous request is processed. Once asynchronous request processing is completed, an asynchronous response is communicated (from the Web server, application server, or Web application) back to the client page. Typically, during this process, the invocation has no impact on Web users; they don't need to wait for the response.
The sequence diagram in Figure 3 illustrates the asynchronous communication model. Take note of the first dataSubmission (with server-side processing) and the first dataSubmission returned, both circled in red. These sequences are decoupled. The illustration also highlights the important fact (detailed later in this section; see Threading issues) that in this mode, multiple submissions (threads) are more likely to occur.
Figure 3. Asynchronous communication sequence
When introducing Ajax into any Web application, development teams need to watch for several hazards, mainly related to the generated HTML page and how it interacts with the browser. These issues are well-documented in Chris Laffra's two-part Considering Ajax series (see Resources). Some of the important points to keep in mind are:
It's natural to try to integrate Ajax development with your Java EE Web framework of choice. But some Java EE Web frameworks do not (yet) offer out-of-the-box support for the asynchronous communication model. To appreciate the implications of this fact, you need to understand the way servlets handle synchronous versus asynchronous communication. Figure 4 shows the traditional servlet sequence for handling a synchronous request:
Figure 4. Servlet sequence for handling synchronous request
Figure 4 should appear rather familiar to Java EE Web developers. A request from the browser is initially handled by the controller servlet's
service(). The servlet can retrieve any value(s) it needs from
HttpRequest (either as a parameter or attribute). Once controller processing is done, the results are sent back into
HttpSession), and the
RequestDispatcher forwards (or includes) control back to the page.
Figure 5 shows the servlet sequence for handling asynchronous requests:
Figure 5. Servlet's sequence for handling asynchronous request
The sequence in Figure 5 is slightly different from the synchronous sequence. A request from the browser is initially handled by the controller servlet's
service(). The servlet can retrieve any value it needs from
HttpRequest (either as a parameter or attribute). Once controller processing is done, the content type of the
HttpServletResponse must be set to XML. Also, the results of the controller logic are written out using the
PrintWriter. At this point, use of the
RequestDispatcher is bypassed.
This is the this exact (asynchronous) sequence that most Java EE Web frameworks do not support, causing integration with Ajax to be difficult. Portlet and JavaServer Faces (JSF) frameworks that don't support the asynchronous communication model face the same issue.
You have some options for overcoming this situation:
- Coexist with the Web framework: Instead of waiting for built-in Ajax support or forcing Ajax support in your framework of choice, you can provide a separate servlet to handle all asynchronous requests. DWR uses this approach. The downside of this approach is that the Ajax request cannot easily leverage your framework's features.
- Integrate with the Web framework: By using freely available extensions or writing a custom one, you can devise a way to integrate with your Web framework of choice.
- Migrate to frameworks that support Ajax: Newer frameworks are beginning to support the asynchronous communication model. One of them is Apache Shale (see Resources).
Heavy use of tag libraries (taglibs) is common in Java Web application development. Like many Java EE Web frameworks, some taglibs don't currently support the asynchronous communication model out of the box, leaving you without a way to translate data submitted via
HttpServletRequest (and vice versa). In essence, taglibs that don't support asynchronous communication become nonfunctional during an invocation of an Ajax
XMLHttpRequest call. Your options are:
- Work around the problem: Use Ajax frameworks that already have a workaround for this problem. One example is DWR (see
ExecutionContext.forwardToString()). In this case, you can continue to use the taglibs you've been using.
- Use Ajax-supporting taglibs: Use taglibs that support the asynchronous model, such as the Ajax JSP Tag Library (AjaxTags) (see Resources).
XMLHTTPRequest and other idiosyncrasies related to Ajax.
In a typical synchronous Web application, some areas require a somewhat longer processing time for a button or link click. Impatient and inexperienced Web users often invoke multiple form submissions by clicking on the button or link more than once, expecting that this will help speed processing time. Other times, users think that a double-click is required (as it is in a desktop application). Multiple form submission in a Web application is harmless in some cases. In others, the side-effects can cause serious threading issues or race conditions (where multiple threads compete for the execution of a code block). For example, multiple clicks to the Transfer Funds button in a banking application could result in unintended multiple transfers.
A Web application that supports both synchronous and asynchronous communication models can find itself in a similar predicament if its functionality isn't properly analyzed and planned for. An application that supports both communication models might mix server-side invocations on a given page (that is, exclusively synchronous, exclusively asynchronous, and a mixture of synchronous and asynchronous). As in the multiple-click scenario, an asynchronous call might process a bit more slowly. And if the application doesn't prevent it, the user might invoke a synchronous call while the asynchronous thread is processing because the page does not refresh and therefore does not prevent further activity on the page. The end result is that the two threads are processed concurrently. Although not originating from the same button or link on the Web page, such situations can cause threading issues (similar to the multiple-click problem) on server-side code.
For example, take the transfer-funds page of a banking application, shown in Figure 6:
Figure 6. Transfer funds example
For the sake of this example, the Transfer Funds button, shown in red, invokes an Ajax call. The Logout link (in yellow) invokes a synchronous call. If an impatient or inexperienced user clicks the red button and the yellow link consecutively (and assuming both links have a common path in the code), a race condition can eventually occur.
Use of Ajax also has the potential to impact performance of a Java EE Web-based application. Two resources are potentially affected by the possibility of allowing additional threads per request.
Another resource that can be affected is the database connection pool. Typical Java EE Web applications enable two types of sequences for a user request: shallow requests and deep requests. Shallow request are requests originating from the Web page that execute server-side code but do not access a persistence store (such as a database) to complete the request. Deep requests are requests originating from the Web page that execute server-side code but do access a persistence store to complete the request.
In the deep-request sequence (assuming a database connection is needed), these aspects of database connection pooling can be affected by allowing more threads:
- The average number of threads waiting for a connection
- The average wait time in milliseconds for a connection
- The average time the connection is in use
As a result, you might need to increase the average size of the connection pool or number of connections.
Introducing Ajax -- just like any other technology or pattern -- into a Java EE application has its advantages and disadvantages. This article has given you the big picture of Ajax integration into Java EE Web applications. Ajax's asynchronous communication model is quite different from the synchronous model that traditional Java EE Web applications are built to support. To avoid being blindsided, be sure to apply ample forethought to the potential problem areas before taking the Ajax plunge.
Support for Ajax within Java EE frameworks and utilities continues to improve. Going forward, look to leverage frameworks with out-of-the-box Ajax support to reduce the complexity of the integration. JSF-based Apache Shale and servlet-based DWR are two that you'll want to keep an eye on.
- Web-Tier Application Framework Design: A brief Model-View-Controller reference from the Sun Blueprints site (including an explanation of the Model 1 antipattern).
- Using Custom Tags to Avoid Scriptlets: The Sun Blueprints site details of the advantages of avoiding scriptlets on the view layer.
- Synchronous and Asynchronous communication: Check out Wikipedia's definitions of these terms.
- Direct Web Remoting: DWR is an easy-to-use Ajax-for-Java framework.
- Ajax for Java developers: Explore Phil McCarthy's developerWorks series to learn more about the pleasures and pitfalls of integrating Ajax into a Java Web application development.
- Ajax JSP Tag Library: A set of JSP tag libraries that supports Ajax.
- Apache Struts: The de facto Java EE MVC framework.
- Apache Shale: The next evolution of Struts, based on JSF.
- "Shale isn't Struts" and "Anatomy of a Shale application" (Brett McLaughlin, developerWorks, February 2006): Popular author and frequent developerWorks contributor Brett McLaughlin introduces Shale in this multi-part article series.
- "Considering Ajax, Part 1" and "Considering Ajax, Part 2": (Chris Laffra, developerWorks, May 2006): A discussion of the impact of Ajax on browser use.
- Ajax in Action (Dave Crane et al., Manning Publications, 2005): A good Ajax book from Manning Publications that includes discussion of a client-side MVC approach.
- The Java technology
zone: Hundreds of articles about every aspect of Java
Get products and technologies
blogs: Get involved in the developerWorks community.
- Ajax discussion forum: A community for Web developers just learning or actively using Ajax.
Patrick Gan is a senior information technology specialist with IBM Global Services. Patrick's expertise is in Java EE, object-oriented application development, and use of open source frameworks. Patrick primarily works on client engagements, assisting clients in the design and development phases of Java EE application development. He is also involved in the design, development, and maintenance of IBM-specific Java EE based frameworks. He has been with IBM for about six years and has a degree in computer science.