JSF and Ajax: Web 2.0 application made easy with Rational Application Developer V7

Ajax is arguably the most popular technology on the Web today, because it's the cornerstone of what is often called Web 2.0. Unfortunately, creating an Ajax application is not an easy task, especially when you need to integrate it with another framework, such as JavaServer™ Framework (JSF). Fortunately, the IBM Rational Application Developer V7 release provides Ajax functionality for the JSF components, which makes the task much easier. This article explains how to use Ajax and JSF together in Rational Application Developer V7 and also walks you through an example of adding Ajax support to an existing application.

Share:

Yury Kats (ykats@us.ibm.com), Advisory Software Engineer, IBM, Intel, Microsoft,HP

Yury KatsYury Kats is a developer in the IBM Rational Application Developer team, working on JSF implementation, components, and tooling.



05 December 2006

Also available in Chinese

Ajax advantages and disadvantages

Although not really new nor revolutionary, Ajax technology has become very popular in the last year or two. Many major Web sites (such as Google, Yahoo!, Amazon, and Netflix) use it to improve their users' experiences. In fact, improving the user experience is what Ajax is all about.

In the usual Web applications developed over the past decade, the interactions between the user and the browser, as well as between the browser and the server, are well-defined and visible: The user sees a page in the browser, takes an action (picks something from a contextual dropdown menu, or selects a few check boxes), and then instructs the browser to communicate with the server by clicking a link or a Submit button. The browser sends a request to the server and passes the user's input in that request. The server processes the request and sends back a response, which is either a new page or the same page, but updated.

Such Web applications are now commonly referred to as Web 1.0. They have two distinct weak points from the user experience point of view:

  • The interaction between the browser and the server is initiated by a limited number of controls on the page -- usually only by links and buttons. Rarely would a server be notified immediately after the user selects a check box on the page or marks a selection in a combo box.
  • The interaction between the browser and the server results in updating the entire browser window. This is often so slow that the user has to wait a significant amount for time for the page to update. Worse, when the same page is reloaded or refreshed, it usually flickers in the browser window.

The new generation of Web applications, commonly called Web 2.0, works around these weak points by using Ajax technology (also AJAX, for Asynchronous JavaScript and XML). In Ajax, interactions between the browser and the server occur in the background, unnoticed by the user. They are also more targeted than the usual browser-server interactions, in that only a subset of the page can be sent to the server, and the server can return only a subset of the page to be updated. As a result of this approach, communication between the browser and server can be initiated by almost any event, such as a selection change in a combo box or a check box or hovering mouse pointer. This results in significant benefits:

  • Communication is faster, because less data is transmitted.
  • The user stays on the same page, because less navigation from page to page is required.
  • The reloaded page does not flicker, because only small regions of the page get updated with each Ajax request.

The ideas behind Ajax are quite simple: Listen for an event in the browser, send a background request to the server, and update part of the page when server responds. But the implementation can be very complicated. It requires in-depth knowledge of JavaScript™, client-server communication protocols, and server-side code. The differences between versions of major browsers make it even trickier to develop and debug. However, the IBM® Rational® Application Developer Version 7 release provides everything you need to develop Ajax-enabled Web applications without having to implement all of the low-level details.

Rational Application Developer V7 provides:

  • Extensions to JSF that allow Ajax requests to be processed within the JavaServer™ Framework (JSF)
  • A JavaScript™ library that can initiate Ajax requests in all recent versions of the major browsers and process server responses by updating only parts of the page

Technical details of the Ajax and JSF implementation in Rational Application Developer V7 are beyond the scope of this article, but let's look into how you can use these two technologies together.


How to use Ajax with JSF components

Adding Ajax to a JSF page is a four-step process:

  1. Identify the area of the page that will be updated by the Ajax request. In Rational Application Developer V7, you can use Ajax with the content of almost any panel component. The panels range from simple containers, such as <h:panelGroup> and <h:panelGrid>, to feature-rich panels, such as menus (<hx:panelMenu>) and dialogs (<hx:panelDialog>).
  2. Select the type of Ajax request to use. There are three different kinds of Ajax requests supported in the Rational Application Developer V7 JSF library:
    • GET request for the same page (<hx:ajaxRefreshRequest>)
    • POST request for the same page (<hx:ajaxSubmitRequest>)
    • GET request for another page (<hx:ajaxExternalRequest>)
  3. Configure parameters to pass to the server with the Ajax request.
    • For GET requests, you can pass values of various input fields on the page.
    • For POST request, the entire form is submitted.
  4. Identify the event that initiates the Ajax request. This can be any client-side JavaScript event, such as onclick for a button, onblur for an input field, or onchange for a check box.

Let's walk through all of these steps, using a simple example of a "Hello, world" type of application. You'll build a page with two fields: input and output. After the user tabs out of the input field, you'll use Ajax to send the value that the user entered to the server and to update the output field with a greeting.

Set up your Web project

To begin, create a Web project (see Figure 1):

  • Select File > New > Project > Dynamic Web Project from the menu.
  • In the New Project wizard:
    1. Enter a project name (for example, HelloWorld).
    2. Select the Faces Project configuration.
    3. Select Add project to an EAR.
  • Click Finish.
Figure 1. New Dynamic Web Project screen
Figure 1. New Dynamic Web Project screen display

To create a Web page (see Figure 2):

  • Right-click the project name in the Project Explorer.
  • Select New > Web Page from the context menu.
  • In the New Web Page wizard, enter a page name (for example, hello).
  • Click Finish.
Figure 2. New Web Page wizard
Figure 2. New Web Page wizard

Add components to the page

Now that you have a page to work with, you'll add the components. You'll use an inputText component for the text field where the user will type a name and an outputText component to show the greeting. Because you're going to update the outputText with Ajax, you need to put it inside of a panel component. You'll use a panelGroup component for this page.

To add the components:

  • Drag an Input component from the Enhanced Faces Components drawer of the palette onto the page.
  • Drag a Panel Group box component from the palette onto the page below the Input component. When you are prompted for the group box type, select Group.
  • Drag an Output component from the palette onto the Panel Group box.

Add Ajax support to the panel

To make content of the panel updatable via Ajax (in this case, an Output field), you need to mark the panel as "Ajaxable" and configure the parameters that you want the user's request to pass to the server. (See Figure 3.)

  1. Select the outputText component and switch to the Properties view.
  2. In the Properties view, select the h:panelGroup tag, which is directly above the h:outputText tag in the left-side tag navigator.
  3. Select the Ajax page for the h:panelGroup tag.
  4. Click the Allow Ajax updates check box.
  5. Select Refresh as the Ajax request type.
Figure 3. panelGroup Properties
Figure 3. panelGroup Properties

This example uses a Refresh request to show how parameters can be passed with an Ajax request. Alternatively, a Submit request would submit the entire form. In that case, because the form on the sample page contains just one input field, you would not need to configure parameters for the Ajax request at all.

To configure parameters for the Ajax request (Figure 4):

  • Select Click to edit Ajax request properties on the Ajax properties page (see Figure 3, shown previously).
  • On the Properties page for the hx:ajaxRefreshRequest tag:
    1. Click Add Parameter for the parameters to send from the browser.
    2. Select the name of the Input component (in this case, text1) from the combo box.
Figure 4. ajaxRefreshRequest Properties
Figure 4. ajaxRefreshRequest Properties

You have configured the panelGroup tag to be updated by an Ajax request and to use the value of the Input field as a parameter for the request. The only thing left to do is to make the outputText component use this parameter to display a greeting (see Figure 5):

  • Select the outputText component.
  • Enter Hello, #{param.text1} into the Value field.
Figure 5. outputText Properties
Figure 5. outputText Properties

Initiate the Ajax request

If you look back to the four steps required to use Ajax, you will see that you have already completed the first three steps. Now you just need to identify the event that will trigger the Ajax request. To update the greeting as soon as the user tabs out of the input field, you'll use the onblur event on the inputText component (see Figure 6):

  • Select the inputText component.
  • Switch to Quick Edit view.
  • In the Quick Edit view:
    1. Select the onblur event in the list of events on the left side.
    2. Click the Use predefined behavior check box.
    3. Select the Invoke Ajax behavior on the specified tag action.
    4. Select the name of the panelGroup (in this case, group1) as the target.
Figure 6. Quick Edit view
Figure 6. Quick Edit view

Now you can save the page and run it on a server. When the browser window opens, you will see an input field and the "Hello" text beneath it. As soon as the user types anything in the field and then tabs out, the greeting will be updated with the text that the user typed in the input field. (See Figure 7.)

Figure 7. Run the Web page on the server
Figure 7. Run the Web page on the server

As you can see, you were able to build a simple yet functional Ajax page with standard JSF components and absolutely no JavaScript code.

Next, let's look into a more complex example.


How to add Ajax to an existing JSF application

Consider a common part of any modern e-commerce Web application: a shopping cart. If you have ever bought anything online, you've seen it. A typical shopping cart shows a list of products that the user added to it while browsing the site, input fields to update quantities, buttons to proceed to checkout, and such.

If you were to look at various shopping carts you'd probably notice at least two things that they have in common:

  • There is usually an Update button that recalculates totals, tax, and shipping cost, based on the quantities that the user entered in the input fields.
  • Each item in the cart is usually a link that takes the user to the product details page.

These are good examples of the weak points that we mentioned at the beginning of this article. The cart is updated only when the user clicks a button, and the user has to navigate to another page to see a detailed description of an item. With Ajax technology, the user's experience could be greatly improved, because the totals can be updated as soon as the quantity changes, and the details for an item can be displayed within the same page (either in a designed area or in a popup window).

In the Resources section at the end of this article, there is a project that you can download that demonstrates how you can easily transfer a Web 1.0 shopping cart to a Web 2.0 application. We'll walk you through this sample application now, so you can see how it was built and how it can be modified to use Ajax.

Note: From this point on, all references (JavaServer Pages™ [JSP™] names, component IDs, and so forth) are to the AjaxSample application that you can download. Please save the AjaxSample.zip file to your computer system, and then import it into Rational Application Developer V7 using the Project Interchange format.

Shopping cart: The old way

The shopping cart in this example uses three Java™ beans: Product, CartItem, and ShoppingCart. You'll find them in the beans package under the Java Resources category in the Project Explorer.

  • Product contains information about products that this site sells: ID, name, description, image, and price.
  • CartItem keeps track of the quantity of each product in the cart.
  • ShoppingCart keeps a list of cart items (product and quantity pairs); calculates totals, tax, and shipping costs; and provides a method to help the user find a product, based on the ID passed in the request parameters.

As Figure 8 shows, cart.jsp is a fairly simple implementation of the shopping cart page.

Figure 8. Shopping cart
Figure 8. Shopping cart

The page uses a dataTable component to display all items in the cart. The Quantity column uses inputText fields to let users change how much to order. After users make all modifications that they want to make, they can click the Recalculate button to update totals, tax, and shipping costs. The name of the product is also a link that takes the user to another page, product.jsp, to see product details. The ID of the product is passed as a parameter. (See Figure 9.)

Figure 9. Product details
Figure 9. Product details

Shopping cart: The new way

Here, cartajax.jsp is the same shopping cart page, but it has been redesigned, using Ajax to improve the user experience. There are three noticeable differences between the new cartajax.jsp (Figure 10) and the original cart.jsp:

  • There is no Recalculate button. The totals update as soon as the user tabs out of an input field.
  • The description of a product is shown in a popup display when the user moves the mouse pointer over the product name.
  • When the user clicks on a product link, full details for the product show underneath the cart, without updating the cart itself.
Figure 10. Shopping cart with Ajax
Figure 10. Shopping cart with Ajax

Let's see how that transformation happened. For illustration purposes, this page uses all three kinds of Ajax requests. Also, unlike at the beginning of this article where you used only IDE features to set up Ajax functionality, here you can see the JSF tags in the Source mode.

Get rid of the Recalculate function

Rather than using a Recalculate button, you declare the panel that contains totals, tax, and shipping as "Ajaxable" by using the ajaxSubmitRequest tag that code Listing 1 shows.

Listing 1. ajaxSubmitRequest code
<h:panelGrid id="totals" styleClass="panelGrid" columns="2" style="text-align:right;">
	<h:outputText id="text4" styleClass="outputText" value="Sub-total:"></h:outputText>
	<h:outputText id="textTotalPrice" value="#{cart.totalPrice}" styleClass="outputText">
		<hx:convertNumber type="currency" />
	</h:outputText>
	... other output components ...
</h:panelGrid> 
<hx:ajaxRefreshSubmit id="refreshTotals" target="totals"></hx:ajaxRefreshSubmit>

You are using a Submit type of Ajax request here, thus there is no need to pass any parameters, because the entire cart form will be submitted. This makes values of all quantity input fields available to the server-side code. The panel and the Ajax tag are connected with the ID and target attributes, which are highlighted in bold in this example (Listing 1). The totals update as soon as the user tabs out of an input field. Therefore, you can use the onblur event of the inputText component to initiate the request:

Listing 2. Code to initiate a Submit request through Ajax
<h:inputText id="textQuantity1" value="#{varproducts.quantity}" styleClass="inputText" 
		size="3">
	<hx:behavior event="onblur" behaviorAction="get" targetAction="totals">
	</hx:behavior>
</h:inputText>

The hx:behavior tag is a very powerful way of attaching predefined JavaScript functionality to client-side events on JSF components. In this case, you are using the onblur event (the event attribute) on the inputText component (hx:behavior is a child of h:inputText), and you want to execute a get action on the totals component. Here, Totals is the panel that you want updated, and the get action means "get content," thus: update using Ajax.

Note: Select cartajax.jsp and then Run On Server to see these tags work together in the browser.

As soon as you tab out of any input field in the table, JavaScript code attached to the onblur event runs. It finds the Totals component on the page, verifies that there is an ajaxRefreshSubmit component associated with it, and then initiates an Ajax POST request by sending the form to the server. When the server responds, the Totals panel is updated with the new content from the server.

Add a popup description

The next example uses a model-less Dialog component (also new in Rational Application Developer V7) to show the description of items in the shopping cart. Because Dialog is a panel, its content can be updated using Ajax in the same simple manner that you updated the panelGroup and panelGrid components earlier (Listing 3):

Listing 3. Use the new Dialog component to show product description
<hx:panelDialog type="modeless" id="descriptionPopup" styleClass="panelDialog"
		style="background-color: #fff9ca" movable="false"
		align="relative" valign="relative" saveState="false"
		showTitleBar="false">
	<h:outputText id="textDescription1d"
		value="#{cart.selectedProduct.description}"
		styleClass="outputText">
	</h:outputText>
</hx:panelDialog>
<hx:ajaxRefreshRequest id="showPopup" target="descriptionPopup"	
	params="$$AJAXROW$$form1:tableEx1:itemid"></hx:ajaxRefreshRequest>

This is very similar to the previous tags, except that this time you are using a Refresh type of Ajax request. Therefore, you need to pass a parameter to the server -- specifically, the ID of the cart item for which you want to see a description. Because your items are in a dataTable, and because JSF keeps only one instance of each component in the table, you must let the server-side code know that you want to use the value of the component in the active row, meaning the row that generated the request. To do this, put the $$AJAXROW$$ key before the ID of the component.

To show or hide the dialog when the user hovers over an item, you can use the onmouseover and onmouseout events of the Link component, as Listing 4 shows:

Listing 4. Code to show or hide the dialog when the user hovers a mouse pointer over an item
<h:outputLink id="link1">
	<h:outputText id="textName1" value="#{varproducts.product.name}"
			styleClass="outputText">
	</h:outputText>
	<hx:behavior event="onmouseover" behaviorAction="get;show"
			targetAction="form1:descriptionPopup;form1:descriptionPopup"></hx:behavior>
	<hx:behavior event="onmouseout" behaviorAction="hide"
			targetAction="form1:descriptionPopup"></hx:behavior>
</h:outputLink>

When the user moves a mouse pointer over an item, you want the content of the dialog to update (a get action) and the dialog to show (a show action). When the mouse pointer is no longer over the item, you want the dialog to be hidden (a hide action).

Show product details on the same page

The final improvement you are going to make is to show product details on the same page, under the shopping cart. You already have the page to show details for an item: product.jsp. Therefore, it would be a shame if you had to go through all of the work that you put into designing it again and reimplement similar tags in the cartajax.jsp. Luckily, you can use an existing JSP file with the help of the third Ajax request type: External request (see Listing 5 ):

Listing 5. Code to show product details on the same page
 <h:panelGrid id="product" width="700" style="margin-top: 20px;"
		styleClass="panelGrid">
	<h:outputText id="text8" styleClass="outputText"
		value="Click on a product to see its details here."
		style="color: gray; font-size: 10pt">
	</h:outputText>
</h:panelGrid>
<hx:ajaxExternalRequest id="showDetails" target="product"
		href="product.faces" source="product"
		params="$$AJAXROW$$form1:tableEx1:itemid">
</hx:ajaxExternalRequest>

You probably already recognize the pattern: a panel component and an associated Ajax tag. The product panelGrid acts as a placeholder for the product details. If the user doesn't select a product, it shows only helper text that explains the purpose of that area of the page to the user. When the user clicks on a product, the content of the panel is updated with a panelGrid similar to that defined in the product.jsp file (the href attribute).

This time, the onclick event of the Link component initiates the Ajax request, as Listing 6 shows:

Listing 6. Code for initiating the Ajax request by using the onclick event
<h:outputLink id="link1">
	<h:outputText id="textName1" value="#{varproducts.product.name}"
		styleClass="outputText">
	</h:outputText>
	<hx:behavior event="onclick" behaviorAction="get;stop"
		targetAction="product">
	</hx:behavior>
</h:outputLink>

The second action in the behavior (stop) is to prevent the event from bubbling up in the browser. You don't want the link to act like a regular link in this case, but only to initiate an Ajax request and then stop processing the event.

The last change that you need to make is about how the ID of the currently selected product gets passed to the server. In the cart.jsp version of the shopping cart, where you used a link to navigate to another page, you defined the ID as a link parameter (Listing 7):

Listing 7. ID defined as a link in the parameter in the original shopping cart
<h:outputLink id="link1" value="product.faces">
	<h:outputText id="textName1" value="#{varproducts.product.name}"
		styleClass="outputText">
	</h:outputText>
	<f:param name="itemid" id="param1" value="#{varproducts.product.id}" />
</h:outputLink>

When using Ajax, you don't have the real link anymore, and you use the params attribute of the Ajax tag to pass a value of a component with the request. Therefore, instead of having a parameter on the link, you need to create a hidden input field that holds the ID next to the link, and use that component as an Ajax parameter (see Listing 8):

Listing 8. Create a hidden ID input field to use as an Ajax parameter
<h:outputLink id="link1">
	<h:outputText id="textName1" value="#{varproducts.product.name}"
		styleClass="outputText">
	</h:outputText>
</h:outputLink>
<h:inputHidden id="itemid" value="#{varproducts.product.id}" />

<hx:ajaxExternalRequest id="showDetails" target="product"
		href="product.faces" source="product"
		params="$$AJAXROW$$form1:tableEx1:itemid">
</hx:ajaxExternalRequest>

With this change, your modifications to the shopping cart are complete.


Other ways to use Rational Application Developer Ajax tools

Although the changes that you made for this exercise showed JSF tags, merely for illustration purposes, you can easily reproduce them with drag-and-drop, Properties view, and Quick Edit view in Rational Application Developer. That's exactly the same process that you used in the first part of this article when you built the "Hello, world" application. Thus, as you have seen here, you can significantly improve the usability of your application, yet you don't have to throw away any work that you already did.


Download

DescriptionNameSize
Sample Ajax application for this articleAjaxSample.zip4.7MB

Resources

Learn

Get products and technologies

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into Rational software on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Rational, Web development
ArticleID=177567
ArticleTitle=JSF and Ajax: Web 2.0 application made easy with Rational Application Developer V7
publish-date=12052006