Web Tier to Go With Java EE 5: Summary of New Features in JavaServer Faces 1.2 Technology
2006-06-12 22:00
831 查看
By Jennifer Ball and Ed Burns, February 2006 |
The first article of the "Web Tier to Go With Java EE 5" series summarizes new features in JavaServer Pages (JSP) 2.1 technology. As that article describes, the biggest contribution of JSP technology is better alignment with JavaServer Faces technology, which was accomplished by unifying the two expression languages (ELs). Alignment with the JSP framework is also one of the more important achievements of JavaServer Faces 1.2 technology, developed through JSR 252. In addition to these changes, JavaServer Faces technology contributes a host of other significant ease-of-use features. This article briefly describes the more substantial ones, which include the following:
Alignment with JSP technology
Ease-of-use improvements in support for custom messages
Improved state-saving behavior
Ability to turn off generation of component client IDs
New
setPropertyActionListenerTag
The Preface section of the JavaServer Faces specification provides a complete list of new features.
Alignment With JSP Technology
The article summarizing new features in JSP 2.1 technology touched on some of these issues. This article gives you more detail on what has changed in JavaServer Faces technology to foster alignment between the two technologies:
First-class support of JSTL's
forEachtag with JavaServer Faces components
Improvements in tree creation and content interweaving
Deprecation of the JavaServer Faces technology EL in favor of the unified EL
First-Class Support of JSTL's
forEachTag With JavaServerFaces Components
As described in the article describing new features in JSP technology, one benefit of unifying the EL in the entire Java EE web tier is that iterating tags such as JSTL's
forEachtag can now be used with JavaServer Faces components in an intuitive way. For example, to render a simple table with input components, you could have the following code:
<table> <tr><th>Item Name</th> <th>Item Price</th> <th>Item Quantity</th></tr> <c:forEach var="item" items="#{shoppingCart.items}"> <tr> <td><h:outputText value="#{item.name}" /></td> <td><h:outputText value="#{item.price}" /></td> <td><h:inputText value="#{item.quantity}" /></td> </tr> </c:forEach> <h:commandButton value="update quantities" action="update" /> </table> |
Improvements in Tree Creation and Content Interweaving
As documented by Hans Bergsten in his article about the use of JavaServer Faces technology with JSP pages, mixing JSP code with JavaServer Faces tags sometimes yielded unexpected results. For example, in the following code, the value of the JavaServer Faces output text component
Hi.should be displayed before the JSP template text
What's your name?
<h:panelGroup> <h:outputText value="Hi. "/> What's your name? </h:panelGroup> |
panelGrouptag are not rendered until after the end-tag of
panelGroupis reached, the text
What's your name?would be rendered before the text
Hi.
Problems such as this and others mentioned in Hans Bergsten's article have been fixed in JavaServer Faces 1.2 technology. The solution involved changing how the component tree is created and how various kinds of content are processed and rendered. The most important changes are the following:
The creation and rendering of the component tree is now split into two steps to prevent the JSP technology engine from rendering content prematurely.
The
rendersChildrenproperties of all standard renderers are now set to
trueso that the body content of the associated components is not rendered separately from the components themselves.
The static content in the body of tags whose renderers have
rendersChildrenset to
trueis captured and stored in a transient
UIOutputcomponent and added to the tree.
State-management tasks have been moved from
ViewTagto
ViewHandlerto prevent
writeStatefrom being called before the state is actually saved.
The upcoming article in the "Web Tier to Go With Java EE 5" series provides a more detailed discussion of the improvements in tree creation and content interweaving, which now make it possible to mix JavaServer Faces component tags with other JSP code.
Deprecation of the JavaServer Faces EL in Favor of the Unified EL
As the previous article in this series explains, the ELs of both the JSP and JavaServer Faces technologies are consolidated into the unified EL. This means that the JavaServer Faces EL is now deprecated. Those of you who had built JavaServer Faces applications prior to the introduction of the unified EL can be assured that your applications are completely backward-compatible.
However, in order to take advantage of the unified EL's features, you will need to change your custom components and custom tags. Migrating to the unified EL primarily involves changing
ValueBindingto
ValueExpressionand changing
MethodBindingto
MethodExpression. These changes are fairly easy to make. Furthermore, the new way of doing things is also easier. For example, because all standard tag attributes are enabled to accept value expressions, your tag handler does not need to check whether an attribute is enabled to accept value expressions.
To get more details on migrating to the unified EL, please see the article "Unified Expression Language."
Ease-of-Use Improvements in Support for Custom Messages
A new set of standard converter messages
New
requiredMessage,
converterMessage, and
validatorMessageattributes for input components
A new
labelattribute for input components, allowing the name of the component to be included in an error message
A new
resource-bundleelement for registering resource bundles with an application
Set of Standard Converter Messages
Prior versions of JavaServer Faces technology included a set of standard error messages to accompany the standard validators. Version 1.2 also includes a set of messages for the standard converters. To see the entire list of messages, refer to section 2.5.2.4 of the specification.
New
requiredMessage,
converterMessage, and
validatorMessageAttributes
In most cases, a standard error message meets your needs. When it does not, you can override it with your own custom messages by using the
requiredMessage,
converterMessage, or
validatorMessageattributes of your input component.
This new feature allows you to override a message when you want to. For example, let's say you are using the length validator on the
useridand
passwordfields. You want to have one message that says
Userid must be 9 charactersand another that says
Password must be 9 characters, but you want to use the same validator for each. With the
validatorMessageattribute, you can set these separate messages on the appropriate components rather than associating one message with every instance of a particular validator.
These attributes accept literal values as well as value expressions, as do most JavaServer Faces tag attributes. Therefore, you can use a value expression to reference a message contained in a resource bundle, as this example shows:
<h:inputText value="#{customer.userID}" validatorMessage="#{customMessages.userIdMessage}" > <f:validateLongRange minimum="9" maximum="9"/> </h:inputText> |
requiredMessageattribute overrides the default message for the required validation failure. The value of an input component's
converterMessageattribute overrides the default message of the converter registered on the input component. Likewise, the value of an input component's
validatorMessageattribute overrides the default message of the validator registered on the input component.
Because of this feature, page authors can now provide error messages that are more tailored to the component using it. Thus, the user can more easily determine the source of the error.
A New
labelAttribute for Input Components
Another feature that helps users decipher error messages is the new
labelattribute for input components. Most standard error messages include substitution parameters that take the name of the component that produced the error. The value of an input component's
labelattribute is substituted at the start of the appropriate default message. For example, the following message is associated with the
DATE_IDmessage identifier of
DateTimeConverter:
{2}: "{0}" could not be understood as a date. |
DateTimeConverterinstance registered on a text-field component, and you set the input component's
labelattribute to
Birth Date. If the user enters
older than the hillsinto the text field, the conversion will fail. When the page is rendered again, the user will see the following error message:
Birth Date: "older than the hills" could not be understood as a date. |
labelcomponent accepts both literal and value expressions. So, as with most other JavaServer Faces tag attributes, you can use an expression to reference the name of the component from a resource bundle.
New
resource-bundleConfiguration Element
Prior to version 1.2 of JavaServer Faces technology, page authors used the
loadBundletag to load a resource bundle into a page in order to reference localized data from a page. Page authors can still load resource bundles into a page using this method in version 1.2.
A new, more efficient way of loading resource bundles involves registering a resource bundle with the entire application by using a
resource-bundleelement in the application's configuration file. The following
resource-bundleelement registers a
ResourceBundleclass named
CustomMessages, which is in the
resourcespackage.
<resource-bundle> <var>customMessages</var> <base-name>resources.CustomMessages</base-name> </resource-bundle> |
varchild element defines the name that page authors will use in expressions that reference the resource bundle, as shown here:
<h:outputText value="#{customMessages.myText}" /> |
myTextis the key that maps to the message in the resource bundle.
With the new
resource-bundleelement, you can load any number of resource bundles into the entire application. Not only does this new element eliminate the need to add a
loadBundletag to multiple pages, but it also has significant performance benefits because loading a resource bundle is an expensive operation.
Improved State-Saving Behavior
The cause of the disoriented application state in multiframe or multiwindow applications was that these multiple logical views within the root view often would have duplicate IDs and would therefore confuse the state-management facility. Several changes to the state-management API in version 1.2 solve this problem.
First, each window or frame within a view now has a unique ID, which is a combination of the view root's ID and a random number that is saved into a hidden field in the form associated with the window or frame. The
writeStatemethod of
ViewHandlerhas been modified to generate the unique ID and write it out to the client during the life cycle's render response phase. Additionally, the
encodeEndmethod
UIFormhas been modified to call
writeStatebefore writing out the markup for the closing tag of the form so that state for multiple forms can be saved.
Also during the life cycle's render response phase, the newly modified
saveSerializedViewmethod of
StateManageruses the unique ID to store the serialized view in the session. For example, if the server crashes, the saved state can be replicated to another server. Therefore, the state-saving mechanism now supports high availability. Finally, the
restoreViewmethod of
ViewHandlernow uses the unique ID to identify the view to restore during the life cycle's restore view phase.
The other major improvement to state saving allows you to encrypt client-side state before including it in the rendered markup that is sent to the client. You can choose to encrypt client-side state by using the
ClientStateSavingPasswordenvironment entry, as shown here:
<env-entry> <env-entry-name> com.sun.faces.ClientStateSavingPassword </env-entry-name> <env-entry-value>somePassword</env-entry-value> <env-entry-type>java.lang.String</env-entry-type> </env-entry> |
Ability to Turn Off Generation of Component Client IDs
[form ID]:[clientID] |
Earlier versions of JavaServer Faces technology did not specify this algorithm well enough for developers to understand how it worked. Furthermore, a custom component or renderer class had no easy way to determine whether the page author had set a component's client ID or the implementation had automatically generated it. Finally, an author of custom renderers might not be able to change the name of the form for one reason or another but might still need to reference its components with JavaScript technology.
This release of JavaServer Faces technology includes a more explicit explanation of the algorithm that generates the client ID. You can find it primarily in the API documentation for
UIComponent. The algorithm has also changed with the addition of the
prependIdattribute on the
UIFormcomponent. Page authors can now change the value of this attribute from the default of
trueto
falseto indicate that the form ID should not be a prefix of the component ID. Table 1 shows the different possibilities for generated client IDs in the most common scenarios.
Table 1: Client ID Generation Scenarios |
Scenario | prependId==true | prependID==false |
---|---|---|
Page author sets no client IDs. | _id0:_id1 | _id1 |
Page author sets the form client ID only. | myForm:_id0 | _id0 |
Page author sets the component client ID only. | _id0:myComponent | myComponent |
Page author sets client IDs of both the form and the component. | myForm:myComponent | myComponent |
setPropertyActionListenerTag
actionListenertag that allows you register a custom action listener onto a component, the core tag library now includes the
setPropertyActionListenertag. You use this tag to register a special action listener onto the
ActionSourceinstance associated with a component. When the component is activated, the listener will store the object referenced by the tag's
valueattribute into the object referenced by the tag's
targetattribute.
To illustrate this tag's usefulness, let's suppose you have a
forEachtag that includes a
commandButtontag and iterates over a list of books, as shown here:
<c:forEach items="#{bookDBAO.books}" var="book" varStatus="stat"> <c:set var="book" scope="request" value="${book}"/> ... <h:commandButton id="add" action="#{catalog.add}" value="#{bundle.CartAdd}"> <f:setPropertyActionListener target="#{requestScope.book}" value="#{book}"/> </h:commandButton> <c:remove var="book" scope="request"/> </c:forEach> |
commandButtontag, the current book is added to the shopping cart, and the next page of the application displays.
If you are familiar with JSTL, you know that the
varattribute of the
forEachtag is always in
pagescope. However, the book data must be in
requestscope so that the page that displays after the user has clicked the button has access to the book data. Therefore, the
setPropertyActionListenertag is used to set the current book object into
requestscope when the user activates the button.
In this case, the
setPropertyActionListenertag's
valueattribute references the book object. The
setPropertyActionListenertag's
targetattribute references the value expression
requestScope.book, which is where the book object referenced by the attribute is stored when the user clicks the button associated with the
commandButtoncomponent.
Conclusion
相关文章推荐
- Web Tier to Go With Java EE 5: Summary of New Features in JSP 2.1 Technology
- Web Tier to Go With Java EE 5: Summary of New Features in Java Standard Tag Library (JSTL) 1.2
- Web Tier to Go With Java EE 5: A Look at Resource Injection
- How to properly logout of a Java EE 6 Web Application after logging in
- Cannot change version of project facet JavaServer Faces to 1.2
- Summary of Useful Features in SQL Server 2008
- 配置tomcat时遇到publishes and runs j2ee and java ee web projects and server configurations to a local to
- Summary of Useful Features in SQL Server 2008
- Developing Web Applications with JavaServer Faces
- Java EE Application with Web Server + Application Server
- Java - How to change context root of a dynamic web project in eclipse
- New replication features in SQL Server 2008 and what they mean to you
- Simplest way to serve static data from outside the application server in a Java web application
- JavaServer Faces 2.0 requires Dynamic Web Module 2.5 or newer..Maven Java EE Configuration
- 奇葩问题:This file could not be checked in because the original version of the file on the server was moved or deleted. A new version of this file has been saved to the server, but your check-in comments were not saved
- Spark - ERROR Executor: Exception in tjava.lang.OutOfMemoryError: unable to create new native thread
- JavaServer Faces 2.0 requires Dynamic Web Module 2.5 or newer..Maven Java EE Configuration
- JavaServer Faces 2.0 requires Dynamic Web Module 2.5 or newer..Maven Java EE Configuration
- Take Advantage of ASP.NET Built-in Features to Fend Off Web Attacks
- JAVA错误:Unable to find config file. Creating new servlet engine config file: /WEB-INF/server-config.wsdd