Sun Java Solaris Communities My SDN Account Join SDN
 

Including Ajax Functionality in a Custom JavaServer Faces Component

By Gregory Murray and Jennifer Ball  

Asynchronous JavaScript and XML (Ajax) is a technique for making the user interfaces of web applications more responsive and interactive. Because of its flexible and pluggable UI component model, JavaServer Faces technology is the perfect framework to use when adding Ajax functionality to your applications. With the DOJO JavaScript toolkit, it's even easier for component developers to add this functionality.  This tutorial describes how to add the power of Ajax to JavaServer Faces components with some help from the DOJO toolkit.
 
Contents
 
What is Ajax?
JavaServer Faces Technology and Ajax
The DOJO Toolkit and Ajax
Using an Ajax-aware Custom Component
Steps to Include Ajax Support in a Custom Component
The Editable Label Example
Creating Necessary JavaScript Functions
Rendering JavaScript Tags With a Custom Renderer
Creating the PhaseListener Class to Handle the Ajax Requests
 


What is Ajax?


If you've surfed the web at all lately, most likely you've seen Ajax in action without realizing it.  Ajax can help increase the speed and usability of an application's web pages by updating only part of the page at a time, rather than requiring the entire page to be reloaded after a user-initiated change.  Through the power of Ajax, the pages of your application can exchange small amounts of data with the server without going through a form submit.  The Ajax technique accomplishes this by using the following technologies:
  • JavaScript that allows for interaction with the browser and responding to events
  • The DOM for accessing and manipulating the structure of the HTML of the page
  • XML, which represents the data passed between the server and client.
  • An XMLHttpRequest object for asynchronously exchanging the XML data between the client and the server.
The following graphic shows how these technologies work together to update a piece of a page with new data from the server.
Sequence of General Ajax Request
                Figure 1: General Sequence of Ajax Request

Figure 1 illustrates the following steps in a generalized Ajax request:

  1.  The user generates an event, such as by clicking a button.  This results in a JavaScript call.
  2. An XMLHttpRequest object is created and configured with a request parameter that includes the ID of the component that generated the event and any value that the user might have entered.
  3. The XMLHttpRequest object makes an asynchronous request to the web server.  An object (such as a servlet or listener) receives the request, processes it, and stores any data in the request to the data store.  In the case of Ajax-aware JavaServer Faces components, the object that processes the request is a PhaseListener object.  We'll cover that more later in the document.
  4. The object that processed the request returns an XML document containing any updates that need to go to the client.
  5. The XMLHttpRequest object receives the XML data, processes it, and updates the HTML DOM representing the page with the new data.
As you can see, Ajax is a powerful new technology, but it has its shortcomings.  Because Ajax is new, it has very inconsistent support among browsers.  Also, to develop with Ajax, you need to have some knowledge of JavaScript, which is out of reach for many page authors.

JavaServer Faces Technology and Ajax


JavaServer Faces technology is designed to make web application development easier for page authors and developers alike.  The most important feature that JavaServer Faces technology offers is its flexible and extensible component model that allows component developers to easily create their own pluggable components.  At the same time, a page author can include a set of components on any of their pages using a component tag library without having to know the details of how a component works.  What's more is that the modularity of the components makes them more toolable.  This means a page author can just drag and drop the components onto a page using a tool such as Sun Java Studio Creator or the NetBeans IDE.

These characteristics make JavaServer Faces technology the perfect companion to Ajax functionality.  Instead of requiring page authors to include JavaScript code on the page itself, component developers can encapsulate it inside the component.  In this way, page authors can make use of all of the Ajax capabilities, while at the same time the complexity of the components' JavaScript is hidden from them. In addition, developers can expose the JavaScript in these JavaServer Faces-developed Ajax-capable components to enable even more powerful interactions.  Furthermore, because the Ajax functionality is encapsulated in the component rather than embedded in the page, the Ajax functionality is more portable and page authors have an easier time maintaining their pages.

The DOJO Toolkit and Ajax


Even with the help of JavaServer Faces technology, adding Ajax support still requires writing some JavaScript, even though it is hidden from the page author.  Although JavaServer Faces technology does help overcome some of the shortcomings associated with using Ajax, it cannot solve all of the problems, such as inconsistent browser support.  

As a result of the problems associated with Ajax, new Ajax frameworks have emerged to overcome them.  Once you learn to master one of these frameworks, you'll find it helps a lot with developing Ajax-aware applications and resolving incompatibility issues and the other common Ajax pitfalls.

One of the frameworks that makes it easier to use Ajax is the DOJO open-source JavaScript toolkit.  First of all, it frees developers from writing more common JavaScript functions by providing pluggable  JavaScript libraries geared toward particular tasks, such as event-handling.  It also overcomes some of the inconsistent browser support of Ajax as well as the memory leaks that plague JavaScript.  Perhaps most importantly to the Ajax developer, it supports the XMLHttpRequest mechanism so that you don't need to deal with it yourself in your JavaScript.

In this tutorial, you'll see how to use DOJO and JavaServer Faces technology to include Ajax functionality in a custom component.

Using an Ajax-aware Custom Component


If you are a page author and you just want to use an Ajax-aware component, you'll be pleased to know that it is as easy as using any other JavaServer Faces component:

1. Include a reference to the component's tag library along with the standard JavaServer Faces tag libraries:

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib prefix="dl" uri="http://java.sun.com/blueprints/dl" %>
 
2. Use the tag in the page:

<dl:dlabel valueBinding="#{SessionBean.name}" />

The rest of what you need, such as the component, renderer, and tag handler classes, as well as the files containing the JavaScript should be packaged by the application developer. 

Check out the list of Ajax-aware components offered by the Java Blueprints Solutions Catalog.  There, you'll find instructions on how to use each component and a screen shot and demo of each component.  See How to Use the Dynamic Text Component for instructions on how to use the component discussed in this tutorial.

Steps to Include Ajax Support in A Custom Component


Adding any kind of Ajax support to a custom component involves a few basic steps.  More complex Ajax support might require additional steps.  The rest of this tutorial assumes that you know the steps for creating a custom component.  If not, please refer to  Creating Custom UI Components.  The basic steps for including Ajax in a custom component are:

  1. Create necessary JavaScript functions, leveraging DOJO as much as possible.
  2. Add code to the component's renderer that will render the JavaScript tags to the page.
  3. Create the PhaseListener class, which handles the Ajax request, interacts with the custom component, and returns an XML document that contains the updated data.
Keep in mind that you also need to perform all the other steps required to create and use a custom component.  This includes creating a tag handler class, a tag library, and a component class.

The next section describes the example used in this tutorial.  When reading this section, you'll see how all the pieces listed in the preceding steps fit together.

The Editable Label Example


The editable label example represents a classic use case of Ajax technology.  This example uses a custom label component that, when you click on it in the page, renders an input component and a  button.  When you enter a string of characters into the input field and click the button, the label reappears with the string you entered.  The rest of the page stays the same; no refresh of the page occurs.

screenshot of the demo
Figure 2: Screen shot of the Editable Label Example

Running the Example


You can see a demo of this example at the Java Blueprints site on java.net.  Go to Library 2 and look for Dynamic Text Label.

To run the example, you need to download the Java Blueprints Solutions Catalog for Java EE 5 bundle.  To do this, follow these steps:
  1. Go to the Java Blueprints site on java.net.
  2. Click Documents & files in the right-hand navigation bar.
  3. Select the bpcatalog-ee5(2) directory.
  4. Download the bpcatalog-ee5-ea-0.6-installer.jar.
  5. Run the installer according to the directions on the page from where you downloaded it.
Once you have checked out the code, do the following:
  1. Obtain the Java EE 5 SDK, install it, and start the Sun Java System Application Server.
  2. Add the Ant build tool included in the Application Server to your path.  It's located in the Applications Server installation's lib/ant/bin directory.
  3. Go to <bpcatalog_install>/bp-project/.
  4. Open build.properties in a text editor.
  5. Set the javaee.home property to the path of your Application Server installation.
  6. Set the javaee.server.passwordfile property to the fully-qualified path to a file that contains your password.  Follow the instructions in the build.properties file.
  7. Save build.properties.
  8. Go to <bpcatalog_install>/apps/webtier/bp-dynamic-text.
  9. Run ant.
  10. Run ant deploy.
  11. Launch a browser and enter this URL:

    http://localhost:8080/bp-dynamic-text/


The Pieces of the Example


The main pieces of this application are the following.  You can browse the source code on the bpcatalog.dev.java.net site.  To see the source, click on the corresponding link below:
  • index.jsp, a JSP page that contains the dlabel custom JavaServer Faces component tags.
  • confirmation.jsp, a JSP page that displays the updated data of the components.
  • DLabel, which defines the custom component.
  • DLabelRenderer, which renders the markup for the components and the script tags that reference the JavaScript files onto the HTML page.
  • DLabelPhaseListener, which processes the Ajax request, exchanges the data with the server-side object, and returns the XML data to the client.
  • SessionBean, which holds the component data on the server.
  • script.js, a JavaScript file that contains the functions used in this application.
  • styles.css, a stylesheet.
  • dojo.js, the JavaScript file that contains all the JavaScript functions supported by DOJO.
Here is a piece of the index.jsp page:

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib prefix="dl" uri="http://java.sun.com/blueprints/dl" %>
...
<f:view>
<h:panelGrid cellpadding="5" cellspacing="0"
columns="2" style="margin-bottom: 20px">
<h:outputText value="Name:" />
<dl:dlabel size="40" valueBinding="#{SessionBean.name}" />
<h:outputText value="Street:" />
<dl:dlabel size="40" valueBinding="#{SessionBean.street}" />
<h:outputText value="City:" />
<dl:dlabel size="40" valueBinding="#{SessionBean.city}" />
<h:outputText value="State:" />
<dl:dlabel size="40" valueBinding="#{SessionBean.state}" />
<h:outputText value="Zip:" />
<dl:dlabel size="40" valueBinding="#{SessionBean.zip}" />  
</h:panelGrid>
...
</f:view>

Each dl:dlabel tag represents one of the label components.  Note that the data for each component is bound to the backing bean called SessionBean

How the Example Works


Figure 3 shows how the example works.

Sequence of Ajax Request in Editable Label Example
Figure 3: Sequence of Ajax Request in Editable Label Example

The following steps explain the architecture illustrated in Figure 3:

  1. The renderer outputs the script tag to the page.
    The index.jsp page contains an HTML script tag rendered by the renderer, DLabelRenderer.  While performing the rendering of the components, DLabelRenderer also creates a hash map with all the component IDs and values.

  2. The page obtains the JavaScript from the phase listener.
    A call is made to the URL, faces/ajax-dlabel-script.js, which is mapped to a FacesServlet instance.  This instance processes the DLabelPhaseListener instance, which recognizes the URL and returns the script.js page containing the client-side JavaScript code necessary for the Ajax interactions. When the page loads, it is initialized, and the initialize function is called.  This function registers all the JavaScript events that are needed for rendering the DLabel component tags on the page.

  3. The user enters a value in the field and clicks the Update Me button to update the data.
    After the user clicks a label and enters a value, he or she clicks the Update Me button, which generates an onclick event.  The updateOnServer JavaScript function, which is mapped to this event, creates an XMLHttpRequest object and configures it with the URL to the FacesServlet instance. If the user changed the Name field to Bob, the URL is faces/ajax-dlabel-update&component-id=Name&component-value=Bob.

  4. The XMLHttpRequest object makes a call to FacesServlet, which updates SessionBean.
    After the URL is configured, the XMLHttpRequest object makes a call to the FacesServlet instance, passing the URL faces/ajax-dlabel-update&component-id=Name&component-value=Bob.  The FacesServlet instance processes the DLabelPhaseListener instance that recognizes the URL the XMLHttpRequest object passed to it.  At this point, the FacesServlet instance also updates the value of the name property in SessionBean.

  5. The phase listener looks up the component ID included in the URL and stores the new data
     DLabelPhaseListener takes the component ID and value that is included in the URL, looks up the component ID and its value from a hash map, and updates it with the user's input.

  6. The phase listener sends the new data back to the page
    The DLabelPhaseListener instance generates an XML document containing the new component ID and value and returns it to the XMLHttpRequest object.

  7. The XMLHttpRequest object updates the HTML DOM with the new data
    The XMLHttpRequest object calls the XMLHttpRequest callback function.  This function updates the HTML DOM based on the contents of the XML document that was returned, and the response is sent back to the client.
The remainder of this tutorial uses this example to explain how to add Ajax functionality to a JavaServer Faces custom component.


Creating Necessary JavaScript Functions


If you are new to JavaScript, you can find a lot of support on the web, including here at java.sun.com.  Be sure to check out  The JavaScript Resource Center.  There you'll discover tutorials, guidelines, and other resources to help you get started.

In any Ajax-enabled JavaServer Faces application, you'll need JavaScript functions to do the following:
  • Register JavaScript events on the components
  • Update the data to the server
  • Render extra components (such as the input field and the Update button in our example) and other changes when onmouseover events occur.
This section discusses how the dojo.event and dojo.io packages help with implementing the Ajax functionality in the application. 

This section does not cover the JavaScript to color the table cells yellow in response to onmouseover events and to render the components in response to onclick events.  The JavaScript required to perform these tasks is fairly standard.  You can get help with it at the JavaScript Resource Center or elsewhere.

The script.js file includes one call to the dojo.event.connect method:

bpui.dlabel = new DLabel();
dojo.event.connect("before", window, "onload", bpui.dlabel, "initialize");
 
This code will ensure that the initialize function is called before the DOJO mechanism initializes. This line also prevents this component's code from interfering with the loading of any DOJO widgets.

The script.js file also uses the dojo.io.bind method call in a few places.  The io package is used to exchange data with the server.  This is the package that encapsulates the XMLHttpRequest mechanism.  So, when using the dojo.io.bind method, you don't need to implement the JavaScript functions that create, initialize, and configure the XMLHttpRequest object, and you are able to hide the calls that XMLHttpRequest makes to the phase listener.  Take a look at the ajax-commons.js file (Select (as plain text) after clicking the link to view the file).  If you weren't using the dojo.io package, you would need to write a script similar to this one to implement the Ajax functionality.

Registering JavaScript Events on the Components


After the page is rendered and the onload event is fired, the initialize function is called.  This function looks up all the tags with the class name of dlabelPlainText with the help of the getElementsByClass helper function. Rendering JavaScript Tags with a Custom Renderer shows how the renderer writes out class name attributes with this value on all the component tags.  After the initialize function finds all the elements with this class name, it will call the updateItem function, which will attach all necessary JavaScript events on them.
   
// key in on the dlabel components by the
className

function getElementsByClass(className){
var found = [];
var elements= document.all ? document.all :   
document.getElementsByTagName("*");
for (var i=0; i < elements.length; i++){
// TODO: Handle multiple classnames
if (elements[i].className==className) {
found.push(elements[i]);

        }
}
return found;
}

this.initialize = function() {
var pageElements = getElementsByClass('dlabelPlainText');
for (var loop = 0; loop < pageElements.length; loop++) {
var pageElement = pageElements[loop];
var itemId = pageElement.getAttribute("id");
var itemValue = pageElement.firstChild.nodeValue;
updateItem(itemId, itemValue);
}
}
 

Updating Data on the Server


The updateOnServer function updates the selected component's value with the user input.  The following piece of updateOnServer shows the parts used to update data on the server.

function updateOnServer(itemId, itemValue) {
var bindArgs = {
url: "faces/ajax-dlabel-update",
method: "post",
content: {"component-id": itemId,
"component-value":itemValue},
mimetype: "text/xml",
load: function(type, data) {
processUpdateResponse(data);
},
...
};
dojo.io.bind(bindArgs);
}

The updateOnServer method passes this set of arguments to the dojo.io.bind method:
  • url: This is the URL that the XMLHttpRequest object passes to the phase listener, which will use it to create an XML document with the component IDs and values.
  • method: This indicates the HTTP method to use when the function is called.  In this case, we want to use POST to post data to the server.
  • content: This attribute contains the ID of the component the user chose to edit as well as the value the user entered into the text field.
  • mimetype: Indicates the MIME type of the content to be passed from the phase listener
  • load: Specifies the function that will be invoked after the XML data is received.
The updateOnServer function calls processUpdateResponse only after it receives the XML data from the phase listener.  Because of this, the client is not updated until the server indicates that the data was updated.  This way, the data on the client matches the data on the server.

When updateOnServer calls processUpdateResponse it passes to it the XML data. 
This function extracts the component ID and value from the XML data, and calls updateItem so that it can be updated in the page.:

function processUpdateResponse(responseXML) {

    // sync the changes with what is on the server
var compId =
responseXML.getElementsByTagName("component-id")
[0].childNodes[0].nodeValue;
var compValue = "";
if(responseXML.getElementsByTagName("component-value")
[0].childNodes[0])
compValue = responseXML.getElementsByTagName("component-value")
[0].childNodes[0].nodeValue;
var status = responseXML.
getElementsByTagName("status")[0].childNodes[0].nodeValue;
updateItem(compId, compValue);
}
 
The next section describes how the custom renderer will render the component tags and the script tag that refers to the script.js file.

Rendering JavaScript Tags With a Custom Renderer


A renderer is used to render the components on the page in the form of markup.  If the renderer is rendering an Ajax-enabled component, it also needs to render the JavaScript tags required by the Ajax mechanism.

A renderer produces the markup tags with its encoding methods.  During the rendering of a page, a renderers encoding methods are invoked whenever the tag of a component that the renderer handles is encountered.

The index.jsp and confirmation.jsp pages of the Editable Label application include several dLabel tags.  The encodeEnd method of DLabelRenderer will be called once for each component tag in the page.  However, we want to render the script tags only once for the entire page.  To accomplish this, DLabelRenderer sets the RENDERED_SCRIPT_KEY request attribute.       

The encodeEnd method of DLabelRenderer invokes the renderScriptOnce method of DLabelRenderer.  This method writes out the JavaScript tags  to the ResponseWriter instance.  Before it renders the script tags, it checks the value of RENDERED_SCRIPT_KEY to determine if the script tag has already been rendered:

private void renderScriptOnce(ResponseWriter writer, 
UIComponent component, FacesContext context)
throws IOException {
Map requestMap =
context.getExternalContext().getRequestMap();
Boolean scriptRendered =
(Boolean)requestMap.get(RENDERED_SCRIPT_KEY);

if (scriptRendered == Boolean.TRUE) {
return;
}

requestMap.put(RENDERED_SCRIPT_KEY, Boolean.TRUE);
...
}

The renderScriptOnce method renders two JavaScript tags.  Each one has a different URL that maps to the FacesServlet instance, by virtue of the fact that the URLs have faces/ appended to the front of them.  Here is the code that writes out on of the script tags to the page:

writer.startElement("script", component);
writer.writeAttribute("type", "text/javascript", null);
String ssrc = "faces/ajax-dlabel-script.js";
writer.writeAttribute("src", ssrc, null);
writer.endElement("script");
 
The phase listener uses the different URLs specified by the src attributes of the tags to determine what processing it will perform.  The actual JavaScript functions are kept out of the page.

After DLabelRenderer completes writing the output to ResponseWriter instance, it saves the component ID and its value into a hash map and puts the hash map into the servlet context:

           
HashMap bindings =
(HashMap)session.getAttribute("dBindings");
if(bindings == null) {
bindings = new HashMap();
session.setAttribute("dBindings", bindings);
}
...
synchronized(bindings) {
bindings.put(baseId, valueBinding);
}
 
DLabelPhaseListener, described in the next section, will use this hash map to retrieve a particular component ID and value so that it can update it.

Finally, DLabelRenderer renders the components themselves inside of div tags and sets the div tags' ID attributes to the components' IDs.  This is because a JavaScript function looks for a tag in a page using the unique IDs of div tags.  Notice that the renderer writes out a class attribute with the value dlabelPlainText.  Recall from Registering JavaScript Events on the Components that the initialize function looks for any elements with this class name and registers JavaScript events on them.

writer.startElement("div", component);
writer.writeAttribute("id", baseId, "id");
writer.writeAttribute("class", "dlabelPlainText", null);
writer.write(value);
writer.endElement("div");
writer.write("\n")
 

Creating the PhaseListener Class to Handle the Ajax Requests


A JavaServer Faces PhaseListener implementation is used to detect when phases of the JavaServer Faces life cycle have begun or completed.  For example, when you implement the  afterPhase(PhaseEvent) method of PhaseListener,  you can perform some processing that will execute after each phase or a particular phase of the life cycle.  This processing can include bypassing the normal JavaServer Faces life cycle rendering mechanism. 

Any JavaServer Faces application that includes Ajax functionality needs a PhaseListener instance to bypass the life cycle so that submission of the page is prevented before Ajax can make changes to the page.  A typical PhaseListener implementation checks the URLs it receives from the script tags to determine how it will handle an Ajax request.

Based on what URL it receives, DLabelPhaseListener does one of the following:
  • Renders the JavaScript to the page based on the URL passed to it
  • Gets the component ID and new value from the request, edits the XML file with the new value, and puts the file into the response.
The phase listener performs these functions before the restore view phase of the life cycle.  It also calls responseComplete when it is finished.  Therefore, it bypasses the rest of the life cycle.  In this way, pieces of the page can be rendered again without going through the entire life cycle and submitting the entire page.

DPhaseListener keeps a set of keys to hold the possible URLs that it will receive:

private static final String SCRIPT_VIEW_ID = "ajax-dlabel-script.js";
private static final String DOJO_VIEW_ID = "dojo.js";
private static final String CSS_VIEW_ID = "ajax-dlabel.css";
private static final String UPDATE_STATE_ID = "ajax-dlabel-update";
 
In its afterPhase method, DLabelPhaseListener obtains the URL from the view ID that identifies the root of the page's UI component tree.  The first time the page is requested, the URL of the view ID is ajax-dlabel-script.js.  In this case the handleResourceReqest method is invoked with script.js:

public void afterPhase(PhaseEvent event) {
String rootId =
event.getFacesContext().getViewRoot().getViewId();
if(rootId.endsWith(SCRIPT_VIEW_ID)) {
handleResourceRequest(event,
"script.js", "text/javascript");
...
}
...
}
 

Rendering the JavaScript to the Page


The handleResourceRequest method creates a connection to the script.js and dojo.js files and streams them to the response.  Once it is finished with this, it calls the responseComplete method, which bypasses the rest of the JavaServer Faces life cycle.

Once the script files are streamed to the response, the JavaScript functions they define can be invoked in response to user-initiated events.  Some of these JavaScript functions pass the URLs to DLabelPhaseListener by way of the XMLHttpRequest object. 

Getting the User Input and Creating the XML File with the New Data


If the user clicks the Update Me button to update data on the server, the updateOnServer function is invoked.  This function passes the URL faces/ajax-dlabel-update to DLabelPhaseListener by way of the XMLHttpRequest object.  When its afterPhase method is invoked during the life cycle, DLabelPhaseListener finds the URL in the view ID and executes its handleAjaxRequest method:

private static final String UPDATE_STATE_ID = "ajax-dlabel-update";
...
public void afterPhase(PhaseEvent event) {
...
} else if (rootId.indexOf(UPDATE_STATE_ID) != -1) {
handleAjaxRequest(event);
}
...
}
 
The handleAjaxRequest method gets the component ID and value from the request parameters.

FacesContext context = event.getFacesContext();
HttpServletResponse response =
(HttpServletResponse)context.getExternalContext().
getResponse();
Object object = context.getExternalContext().getRequest();
if (!(object instanceof HttpServletRequest)) {
return;
}
HttpServletRequest request = (HttpServletRequest)object;
HttpSession session = request.getSession();
String compId = request.getParameter("component-id");
String compValue = request.getParameter("component-value");

 
It then finds the component ID in the hash map that contains all the component IDs and values and resets its value with the user's input.

ValueExpression valueBinding = (ValueExpression)
((HashMap)sContext.getAttribute("dBindings")).get(compId);
valueBinding.setValue(context.getELContext(), compValue);
 
Finally, handleAjaxRequest creates the XML output with the component ID, compId, and component value, compValue, and sends the XML to the response, as shown in the following code.

String message = "success";
StringBuffer sb = new
StringBuffer();
sb.append("<message>");
sb.append("<component-id>" + compId + "</component-id>");
sb.append("<component-value>" + compValue + "</component-value>");
sb.append("<status>" + message + "</status>");
sb.append("</message>");
try {
response.setContentType("text/xml");
response.setHeader("Cache-Control", "no-cache");
response.getWriter().write(sb.toString());
} catch (IOException iox) {
System.err.println(
"DLabelPhaseListener error writing Ajax response : "
+ iox);
}
 
At this point, the XML content is passed back to updateOnServer by way of the XMLHttpUpdateResponse object.  The updateOnServer function then  passes the XML data to the processUpdateResponse JavaScript function.  The JavaScript functions will update the page with the new value.

Conclusion


As this tutorial explains, Ajax significantly improves the user's experience with an application.  JavaServer Faces technology makes adding Ajax-enabled components easier for the page author, while maintaining the flexibility enjoyed by the component developer.  Finally, the DOJO toolkit makes adding Ajax functionality to a component easier for the component developer.  As Ajax and the various Ajax frameworks mature, problems such as the browser incompatibilities will likely disappear.  In the meantime, using JavaServer Faces technology and DOJO to create Ajax-aware, pluggable components is one of the best solutions out there.

For More Information


Ajax Developer Resource Center
JavaScript Resource Center
JavaServer Faces Technology
Java Blueprints Solutions Catalog
Sun Java Studio Creator
NetBeans
DOJO JavaScript Toolkit