JSF Central - Speed up your Data-Driven JSF/Seam Application by Two Orders of Magnitude – Part 2
JSF Central

 
 Home 
 
 Products 
 
 Articles & Books 
 
 Resources 
Speed up your Data-Driven JSF/Seam Application by Two Orders of Magnitude – Part 2
 
Speed up your Data-Driven JSF/Seam Application by Two Orders of Magnitude – Part 2
by Dan Allen
27 Mar 2009 01:30 EDT

In the second installment of this two-part article, Dan Allen continues his discussion of some common performance problems you may encounter when using JSF components, Seam components, and the EL. You'll learn about the set of best practices for eliminating them that led to an improvement of two orders of magnitude in the performance of his application.


In the first part of this article, I began briefing you on optimizations I made to maximize the responsiveness of a JSF application that I developed out in the field. I cited performance problems caused by casually accessing components from a JSF view, then presented a set of best practices to eliminate this unnecessary overhead. Despite the progress made by the end of the first part, you had not yet witnessed the two orders of magnitude in performance improvement that was promised.

In this part, the additional gains will be achieved by leveraging partial page rendering-provided by the RichFaces JSF component library and by slimming the response. Partial page rendering cuts out the overhead of rerendering the entire page after each user interaction, which turns out to be the real bottleneck in most traditional web applications, and instead redraws only the areas of the page that have changed. Naturally, you want the replacement HTML source to be as condensed as possible. These optimizations allow the responsiveness of a web application to measure up to its desktop counterpart.

Tapping into Ajax

When the user performs an operation on the screen, such as selecting a row for editing or paginating a result set, we only want to rerender the area of the page that is affected. Using the data-driven application presented in the first part, that means redrawing the data table and its pagination controls. (Note that it's possible with Ajax4jsf to rerender a single row, when applicable, but I have found it to be more trouble than it's worth).

Putting numbers aside, using Ajax is going to make the application feel far more responsive because the browser does not have to bootstrap a whole new page and all the assets that come along with it. Research has shown that creating HTTP connections is more costly than rendering large pages. Partial page rendering accounts for these findings by treating the static areas of the page and its associated assets as completed work, and focusing solely on retrieving updates. This section will support my recommendation that you should always consider using Ajax in your application, as it truly does eliminate a lot of overhead.

Accessible Ajax with Ajax4jsf

Turning regular JSF postbacks into Ajax requests is pretty simple with Ajax4jsf. However, if used inappropriately, you won't get all the performance gains you are looking for. We'll get to that in a second. First, begin by changing your <h:commandLink> and <h:commandButton> components to the ones from Ajax4jsf: <a:commandLink> and <a:commandButton>. Next, select what you want to rerender. You reference the areas of the page to update using a comma-separated list of the regions' component IDs in the reRender attribute of the command component. If you are paginating, you need to rerender the whole table and the pagination controls (dataTableContainer). If you are transitioning into edit mode, there's no need to requery or update the pagination, so you only have to rerender the table itself. Here's the code for the pagination controls:

<a:commandLink id="previous" action="#{benthicMsmntEditor.previous}" rendered="#{benthicMsmntEditor.previousAvailable}" reRender="dataTableContainer" ajaxSingle="true"> <h:graphicImage value="/img/previous.png" alt="Previous" title="Previous"/> </a:commandLink> <a:commandLink id="next" action="#{benthicMsmntEditor.next}" rendered="#{benthicMsmntEditor.nextAvailable}" reRender="dataTableContainer" ajaxSingle="true"> <h:graphicImage value="/img/next.png" alt="Next" title="Next"/> </a:commandLink>

The code for the edit control buttons in each row is similar. Here's how the edit button is defined: <a:commandLink id="edit" action="#{benthicMsmntEditor.editItem}" rendered="#{_item != conversationScope.get('itemInEditMode')}" reRender="dataTable" ajaxSingle="true"> <h:graphicImage value="/img/edit.png" alt="Edit" title="Edit"/> </a:commandLink>

What's important about using an Ajax request is to keep it simple. You don't want to perform a lot of processing on the server because then the users aren't going to get the "instant" feedback they are expecting. You can drastically reduce the portion of the component tree that is processed by JSF by using either the <;a:region> tag or the ajaxSingle attribute on an Ajax4jsf component. Let's focus on ajaxSingle.

Keeping the Ajax call brief

By default, JSF processes the whole component tree on a postback because it doesn't know where events may originate or which input fields within the submitted form contain new data. What the ajaxSingle attribute does is tell JSF to advance directly to the component that was activated, process events from that component, and re-encode it as if it were the only component on the page. The result is a drastic speed increase in the processing, independent of the size of the component tree. In fact, the only time you would forgo using ajaxSingle is when you need to capture input data from a form (a classic form submit).

When deciding whether or not to use this attribute, ask yourself if you are capturing form data or whether JSF is simply using the form submit to perform server-side work (a contrived form submit). In JSF, it's most often the latter.

Note: Interestingly enough, ajaxSingle is also a drop-in replacement for immediate, which is excellent since immediate is so poorly understood. When ajaxSingle is placed on a command component (such as a button), the form data is not processed, and hence no validation/conversion failures can occur, thus eliminating the need for immediate.

Having shifted all interactions to the Ajax bridge, it's now time to look at the performance gains. Of course, when using Ajax, the tax of rendering the portions of the page outside of the data table is gone. The performance on the server is also no longer a primary concern. Now what matters is the size of the response. Unfortunately, giving timing results here would be arbitrary because it's highly dependent on the speed of the network (and I'm testing against my own box). We have to focus on what we can control.

Trimming down the response

So what affects response size? The answer is, every character in the view. Every character that you type that is encoded into the response, as well as the markup that the JSF components generate, affects the size of the response. That includes:

  • Component IDs
  • View IDs
  • The path of images, external JavaScript files, and CSS
  • The application context path
  • Embedded JavaScript
  • Inline styles and names of style classes
  • Erroneous markup that is encoded into the response

As you can see, there's lots of room for improvement in this category. I want to focus on component IDs first, since they are the biggest culprit.

Resources



RSS feed(all feeds)

The Editor's Desk
Podcasts
Inside Facelets
In the Trenches

Site version 1.83  Report web site problems

Copyright (C) 2003-2014 Virtua, Inc. All Rights Reserved. Java, JavaServer Faces, and all Java-based marks are trademarks or registered trademarks of Oracle Corporation. in the United States and other countries. Virtua, Inc. is independent of Oracle Corporation. All other trademarks are the sole property of their respective owners.