`
zengjinliang
  • 浏览: 300651 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

Adding Ajax to JavaServer Faces Technology With Dynamic Faces

阅读更多

Article

Adding Ajax to JavaServer Faces Technology With Dynamic Faces

 

This article shows how to use Project Dynamic Faces, included in the new Sun Web Developer Pack, to add first-class Ajax support to your JavaServer Faces technology-based application.

Beginning with an existing sample application, Virtual Trainer, from the book that the article's author wrote with Chris Schalk, JavaServer Faces: The Complete Reference, this article will show you how to add Ajax behavior to two of that application's pages. This example will illustrate two usage patterns for Project Dynamic Faces and also provide a springboard for discussing the Ajax techniques that Dynamic Faces employs.

First, this article will go through the Virtual Trainer application and call out the places where you will add Ajax features.

The application's welcome page contains two links at the upper right: Register and Login. The Sign Up Today! link at the bottom of the page points to the same page as the Register page. Click Register.

The screen capture in Figure 1 shows the non-Ajax version of the registration page. As you can see, this is a garden-variety JavaServer Faces technology-based page. Fill out the form but use

jake

for the Userid text field, and submit the form.

Once you get past the validation errors, you will see the message

Userid jake already exists! Please choose another.

Wouldn't it be nice if there were a button next to the Userid field that would allow the user to fire an Ajax request off to the server, sending only the user ID and checking only whether that user ID is available? With a few lines of code, you can create this functionality.

Now click the Login link in the application, and use

jake

as both the user ID and the password. Once logged in, you will see a table of training events, as shown in Figure 2. Choose one training event by clicking the Select link at the right of the desired row.

You now see a page allowing the trainer, jake, to advise the trainee on how to train for the selected event. For every training session for which the user has selected Completed in the table, the user will be able to type in the Personal Notes field only if the Completed checkbox is not checked. If you deselect a Completed checkbox and click the Update Event button, the Personal Notes field becomes editable.

But why bother with the extra step of clicking the Update Event button? With a few lines of code, you can remove the Update Event button and enable the application to update the form with Ajax whenever the user selects the checkbox. Download the Java Platform, Enterprise Edition (Java EE) SDK or the Platform Edition of Sun Java System Application Server version 9.0 or 9.1, and install and configure it according to the instructions that come with the download. Also download the Sun Web Developer Pack (SWDP) and follow the instructions to install it on top of the SDK or Application Server. The rest of this article assumes you are using NetBeans IDE 5.5 to build and run the example, though you need not do so.

For maximum ease, install the NetBeans IDE modules that come with the SWDP according to the instructions provided in the SWDP download. Doing this will make it easy to add Dynamic Faces support to your application.

Now download the source bundle for this article and the original source for the Virtual Trainer application. Once you have the NetBeans IDE and the SWDP modules installed, open the Virtual Trainer NetBeans project from the article download. Right click on the Virtual Trainer project and choose Properties. Highlight the Libraries tab and make sure that

SWDP-jsf-extensions

is in the list.

Finally, modify the application's

web.xml

file to enable the Ajax life cycle supplied with Dynamic Faces. Locate the

<servlet>

declaration for the

<servlet-class>

javax.faces.webapp.FacesServlet

. In this declaration, add the following XML:

<init-param> <param-name>javax.faces.LIFECYCLE_ID</param-name> <param-value>com.sun.faces.lifecycle.PARTIAL</param-value></init-param>

 

This advises the

FacesServlet

to use the Ajax life cycle instead of the standard JavaServer Faces request processing life cycle. The Ajax life cycle decorates the standard one and adds the handling necessary for Ajax. Listing 1. If you have correctly installed the NetBeans SWDP modules, you should see autocompletion in the

uri=""

entry, and you should be able to choose from the list.

Add an attribute to the

<h:form>

tag:

prependId="false"

 

This new attribute in JavaServer Faces 1.2 technology advises the JavaServer Faces runtime to not prepend any naming container IDs to your component IDs within the form. The result is that the IDs you type in the markup are the actual ones that appear in the page. This is important in reducing page size and in making it easier to address markup from JavaScript code. This is line 16 in Listing 1.

After the

<h:form prependId="false" />

add the following line:

<jsfExt:scripts />

 

This is one of two tags in the Dynamic Faces tag library, and it simply instructs the runtime to render the

<script>

h:inputText>

, add the following code:

<h:commandButton value="#{res[\'register.userIDAvailableButton\']}" actionListener="#{Register_Backing.checkUserIDAvailable}" return false;" /><h:outputText style=" {color: red}" value="#{requestScope.userIDAvailableMessage}" />

 

This is line 88 in Listing

as the last JavaScript line in the

onclick

handler.

The arguments to the

DynaFaces.fireAjaxTransaction()

function are fully explained in the Project Dynamic Faces reference materials, but let's look at what you need for this example.

The first argument is the JavaScript reference to the Document Object Model (DOM) element that originates this Ajax transaction. The second argument is a JavaScript associative array of

name: value

pairs that describe the options given to this transaction. In this case, you have three options:

execute

,

render

, and

immediate

.

The

execute

option is a comma-separated list of JSF client IDs that will be traversed during the

execute

portion of the JSF request processing life cycle. Normally in JavaServer Faces technology, the entire view is traversed during this part of the life cycle, but with Dynamic Faces, you can control what subtrees in the view are traversed. Note that each client ID named in this list, along with any children of those nodes, will be traversed. For a review of the JavaServer Faces life cycle, see the Sun Web Developer Pack Tutorial.

In this example, you want the

execute

portion of the life cycle to hit the

userid

and the

userIDAvailable

nodes. These IDs correspond to the

<h:inputText>

for the user ID and the

<h:commandButton>

for the button to check for ID availability, respectively. You want to make sure that only these nodes are traversed because you need the user ID that the user entered to be submitted, and you want the

actionListener

for the button to be executed.

The next option is

render

. Like

execute

, this option is a comma-separated list of client IDs. But unlike

execute

, this list names the subtrees to be traversed during the

render

portion of the JavaServer Faces life cycle. In this case, the value is

userIDAvailableMessage

, which is an

<h:outputText>

, as shown on line 93 of Listing 1. The

userIdAvailableMessage

component simply outputs a request-scoped attribute that is named

userIDAvailableMessage

.

The last option is

immediate: true

. This option is like the

immediate

option on JavaServer Faces components, except that it has an effect only on this particular run through the life cycle. Its operation and intent is exactly the same as in core JavaServer Faces technology. For more on the

immediate

attribute, see the book JavaServer Faces: The Complete Reference. That's it for the rendering side of the activity.

 

Listing 2 shows a

diff

, a file comparison showing the difference between two versions of the same file, of the

register.jsp

file before and after the changes that this article discusses. As you can see, the author of this article added or changed only 11 lines.

Listing 2:

diff

of Old and New

register.jsp

Files

1. <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%> 2.  <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%> 3. +<%@ taglib uri="http://java.sun.com/jsf/extensions/dynafaces" prefix="jsfExt"%> 4.  <f:view> 5.    <f:loadBundle basename="com.jsfcompref.trainer.resources.UIResources" 6.                  var="res"/> 7.  -12,7 +13,8 @@ 8.        <link href="css/vt.css" rel="stylesheet" media="screen"></link> 9.        <link rel="shortcut icon" href="images/favicon.ico"> 10.      </head> 11. -    <body><h:form> 12. +    <body><h:form prependId="false"> 13. +        <jsfExt:scripts /> 14.          <table width="100%" border="0"> 15.            <tr> 16.              <td> 17.  -81,10 +83,17 @@ 18.                  <f:verbatim>&nbsp;</f:verbatim> 19.   20.                  <h:outputLabel value="#{res[\'register.userid\']}" for="userid"/>                21. -                <h:inputText required="true" 22. +                <h:inputText required="true" autocomplete="off" 23.                               binding="#{Register_Backing.userid}"/> 24. +                <h:commandButton 25. +                  value="#{res[\'register.userIDAvailableButton\']}" 26. +                  actionListener="#{Register_Backing.checkUserIDAvailable}" 27. +                                       render: return false;" /> 29. +                <h:outputText style="{color: red}" 30. +                         value="#{requestScope.userIDAvailableMessage}" /> 31.                  <h:message for="userid" errorClass="ValidateError"/> 32. - 33. +<br /> 34.                  <h:outputLabel value="#{res[\'register.password\']}" for="password"/>                35.                  <h:inputSecret required="true" 36.                               binding="#{Register_Backing.password}" />

 

Listing 1:

actionListener="#{Register_Backing.checkUserIDAvailable}"

 

Listing 3 shows this new method. This is a plain-old JavaServer Faces

ActionListener

method. It does not do anything specifically Ajax-related, but because you are using Dynamic Faces, it will be invoked by Ajax. On line 2 of Listing 3, you get the value of the Userid field. Note that this component is bound with a JavaServer Faces component binding, as shown on line 87 of Listing 1. For more detail on component bindings, see the book JavaServer Faces: The Complete Reference.

Because you are running the full JavaServer Faces life cycle, you know that the value has been validated and converted according to any validators or converters attached to the component.

Line 3 of Listing 3 uses a class specific to the Virtual Trainer application,

UserRegistry

, which provides a handy method,

userIdAlreadyExists

. You simply pass the user ID from the text field to this method and store a message in request scope, as shown on lines 4 through 14 of Listing 3.

Because this application is already internationalized, you will use the

ResourceBundle

for the application to get the message. Note that you are passing the current locale from the

ViewRoot

into the

ResourceBundle.getLocale()

method. This ensures that the language settings sent by the browser are correctly handled with respect to the supported localizations for this application.

Sun Web Developer Pack Tutorial. Project Dynamic Faces reference materials. Briefly, putting components within an Ajax zone causes them to be imbued with Ajax behavior such that clicking on the element will cause an Ajax transaction to the server, allowing just those components within the zone to update themselves by way of Ajax. The Sun Web Developer Pack Tutorial describes how to make action in one zone cause a reaction in another zone, all by way of Ajax. Source code for this bundle

Original source for the virtual trainer application

Download the Java EE SDK

Sun Web Developer Pack Tutorial

JavaServer Faces technology

Ajax Developer Resource Center

Ed Burns's blog

About the Author

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics