http://andyschwartz.wordpress.com/2009/07/31/whats-new-in-jsf-2/#scopes
With so many sources of information available on JSF 2, why bother with another overview? After all, this ground has already been covered quite extensively:
Mojarra team members Jim Driscoll and Ryan Lubke have been doing a thorough job blogging on new 2.0 features.
The Seam team has provided very insightful background on requirements that drove many of the key JSF 2 features.
David Geary has published an excellent introduction to JSF 2 with his three-part article series.
Ed Burns has provided a Webinar, slides, data sheet, interview and much JSF 2 coverage in his blog.
Cay Horstmann’s JSF 2.0 Refcard and slides are also full of helpful information.
Kito Mann has done a great job keeping JSFCentral up to date with the latest JSF-related interviews, podcasts, editorials, articles and blogs.
And, of course, there is always the good old specification, JavaDoc, tag documentation and, new in JSF 2.0, JavaScript documentation.
One problem I have been facing is deciding where to point my Oracle colleagues who are interested in a quick introduction to the JSF 2.0 feature set. The spec contains all of the information, but that’s some pretty heavy reading. The blogs do a phenomenal job of covering specific features but do not provide a big picture overview. The Webinar provides the big picture overview, but some folks might prefer reading over listening/watching. The slides also provide an overview, but I wanted something with more prose than bullets.
So, on the theory that more is good, and since I could not find quite what I was looking for, I decided to spend some time writing up my own take on the new JSF 2.0 feature set. Of course, I borrowed from all of the above sources while working on this, so many thanks to my JSF colleagues for making my job easier!
Note that I do not attempt to cover these features in extreme detail. This is just an overview. However, each section includes links to more detailed information where available, so please click through if you do not find the level of detail that you need here.
Contents
View Declaration Language and Facelets
Composite Components
Ajax
Ajax Request Lifecycle
State Saving
System Events
Navigation
Implicit Navigation
Conditional Navigation
Preemptive Navigation
GET Support
View Parameters
PreRenderView Even
Scopes
View Scope
Flash Scope
Custom Scopes
Configuration
Managed Bean Annotations
Component Annotations
Faces-config.xml Ordering
Project Stage
Behaviors
Validation
Bean Validation
Empty Field Validation
New Validators
Error Handling
Resource Loading
Tree Visiting
View Declaration Language and Facelets
Not to knock JSP, but even JSP champions must admit: JSP as the primary view technology for JSF has not been a walk in the park. The problems have been discussed for years, dating back to the now classic Improving JSF by Dumping JSP, published back in 2004 just months after the JSF 1.0 spec was released. As of JSF 1.2/JSP 2.1, several of the key issues have been addressed. However, the JSF/JSP combination certainly has room for improvement.
The JSF community has not been sitting still. Several JSF-optimized alternatives to JSP have emerged, including Apache Shale’s Clay (now retired), JSFTemplating and Facelets. However, the lack of a standard solution remains a sore point for JSF users. JSF 2.0 recognizes the need for a standard alternative to JSP and addresses this by taking two steps.
First, JSF 2 provides a generic foundation for integrating view declaration languages into the JSF runtime environment. The ViewDeclarationLanguage API defines the contract through the JSF runtime interacts view declaration language implementations in order to complete tasks such as building up the component tree. This contract allows framework authors to define their own view declaration languages and integrate these with JSF in a standard way.
Second, JSF introduces the first standard non-JSP view declaration language: Facelets! JSF 2.0 includes a re-purposed version of the Facelets 1.x API/implementation. This 2.0 version of Facelets should be very familiar to anyone who has been using Facelets 1.x. Most of the 1.x APIs are present, though there has been some tweaking/repackaging as part of the standardization process.
The inclusion of Facelets as a standard view declaration language should ease any concerns that development teams may have about embracing this technology.
While Facelets is a new focus for the JSF specification, JSP support is still available for those users who are not ready to make the jump to a new view definition technology. Note, however, that the JSP side of the JSF specification is basically standing still. None of the new features that involve new tags (composite components, system events, Ajax, etc…) are exposed through JSP.
Links
Issue 274 JSFPDL – JSF Specific Page Description Language
Improving JSF by Dumping JSP
Facelets
JSFTemplating
Clay
ViewDeclarationLanguage (JavaDoc)
Composite Components
Let’s take a quick look at how to implement a custom component in JSF 1.x: Just implement your UIComponent subclass, and… done! Oh,wait… you might want to move your markup rendering code into a Renderer. Oh, and don’t forget to register your component and renderer in a faces-config.xml file. Er… then you just need to implement your JSP tag. Oh, and don’t forget that tld!
Okay, so JSF custom component development has always been a chore. The problems have long been known and are well documented.
JSF 2 greatly simplifies custom component development with the introduction of the “composite component” feature. This feature allows a custom component to be implemented with a single file – no Java code required.
Let’s take a look at the obligatory “Hello, World!” example, starting with a composite component that renders the salutation:
01
02
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
03
xmlns:h="http://java.sun.com/jsf/html"
05
xmlns:composite="http://java.sun.com/jsf/composite">
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
The composite component is defined via an XML file containing XHTML contents plus elements from the “http://java.sun.com/jsf/composite” namespace. The
To make the composite component available for use, we simply drop this file into a “resources” directory (more on resource loading later). The tag name for the composite component is derived from the file name. The tag namespace is based on the location of the composite component within the resources directory.
If we dump the above code in a “Hello.xhtml” file inside of a “resources/greet” directory, we end up with the following:
Tag name: hello
Tag namespace: http://java.sun.com/jsf/composite/greet
We can then reference our new component as follows:
1
xmlns:h="http://java.sun.com/jsf/html"
3
xmlns:greet="http://java.sun.com/jsf/composite/greet">
4
5
6
7
8
9
That’s quite a simplification from earlier days of writing UIComponent subclasses, renderers, tags, faces-config.xml entries and tlds!
The composite component architecture is much more sophisticated than demonstrated with this minimal sample. Support for all of the usual component-centric functionality is provided, including inserting facets, adding children, attaching listeners, validators, converters, etc… See the links below for more extensive coverage of JSF 2 composite components.
Links
Issue 273: Make developing custom components easier
Issue 280 Composite Components
Jim Driscoll’s blog contains much useful information on composite components, including more detailed samples.
Building a JSF Component with AJAX – It’s Easy!: Slides from Jim and Ryan Lubke’s JavaOne BOF.
Templating and composite components: Part 2 of David Geary’s article series covers both Facelets templates as well as composite components.
True Abstraction: Composite UI Components in JSF 2.0: A two-part article by Ed Burns on composite components.
Ajax
Here we are, 2009, four years since the term Ajax was coined. Hasn’t the JSF/Ajax integration problem been solved yet?
Well, actually, yes, it has. If the JSF AJAX Component Library Feature Matrix is any indication, this problem has been solved many times!
The availability of so many JSF/Ajax frameworks is a good indication that JSF provides a strong foundation for Ajax. So, does that mean that we are done? What’s left for the JSF spec to do?
Well, two things actually:
Compatibility. While it is impressive that so many JSF/Ajax solutions are available, the subtle differences between these solutions lead to cross-framework compatibility problems.
Native Support. Isn’t it time that JSF users have access to Ajax functionality without requiring a 3rd party framework?
JSF 2 attempts to address both of these issues by providing various new Ajax-related APIs and infrastructure. Let’s take a look at these by walking through the lifecycle of a typical Ajax request.
Ajax Request Lifecycle
Starting on the client, JSF 2 exposes a new JavaScript API, jsf.ajax.request(), that issues an Ajax request back to the current view. This method collects any data that needs to be included with the request, prepares the request payload, registers a response handling callback and then posts the request back into the Faces lifecycle.
Once the request enters the Faces lifecycle, the state of the Ajax request is captured via the PartialViewContext. This object provides access to information such as which components are targeted for processing/rendering. The PartialViewContext’s processPartial() method uses this information to perform partial subtree processing/rendering.
When the rendered response is sent back to the client, the callback previously provided by jsf.ajax.request() is invoked. This callback automatically updates the client-side DOM to reflect the newly rendered markup.
In order to encourage compatibility across JSF components/frameworks, the request and response payloads have also been standardized.
The jsf.ajax.request() JavaScript API is a primitive that is primarily targeted for use by frameworks as well as by the JSF implementation itself. JSF 2 also includes a declarative approach that is intended to be more convenient for page authors. This approach leverages the new
Instead of manually coding the JavaScript for the Ajax request call:
1
Page authors can declaratively specify the same behavior:
1
2
3
The presence of the
Links
Issue 293 Ajax umbrella issue
Pretty much just go read Jim Driscoll’s blog.
jsf.ajax.request() (JSDoc)
PartialViewContext (JavaDoc)
State Saving
JSF state saving has long been a sore point, both for application developers as well as component developers. The main problem for application developers is that the size of the saved state can be large. This makes client-side state saving impractical and leads to session state bloat. For component developers, the issue is that implementing saveState and restoreState methods is tedious and error prone.
JSF 2.0 addresses these issues with the introduction of a new “partial” state saving mechanism. This solution was inspired by a proposal that Adam Winer made (and implemented in Apache Trinidad) over 3 years ago. The key concept is that saving the entire state of the component tree is redundant, since the component tree can always be restored to its initial state by re-executing the view (ie. by re-executing Facelet handlers to re-create the component tree).
If we use the view definition to restore the component tree to its initial state, then the only state that needs to be saved is state that has been modified since the view was initially created. And since in most cases the number of components that are modified after component tree creation is small, the size of this delta state is typically much smaller than the full component tree state.
A requirement for the delta/partial state saving approach is that component implementations must know when their initial state has been fully configured. JSF 2 introduces the PartialStateHolder contract to help with this requirement. The PartialStateHolder’s markInitialState() method is called to notify the implementing component that its intial state has been established. Only modifications that occur after this notification need to be saved.
A second API has been introduced to help component implementations manage their state: StateHelper. The StateHelper provides storage for component state (such as attributes, listeners, etc…) and relieves the component author from having to provide custom saveState and restoreState implementations.
As a result of these new APIs, JSF 2 state saving is both more efficient and easier to use!
If the PartialStateHolder/StateHelper APIs seem vaguely familiar to you, you just might be thinking of Apache Trinidad’s FacesBean.
Links
Issue 272 StateManagementRevision
How we’re going to fix JSF state saving
PartialStateHolder (JavaDoc)
StateHelper (JavaDoc)
System Events
JSF 1.x includes two event delivery mechanisms. FacesEvents are delivered to FacesListeners in response to user interaction, such as editing an input component, or activating a command component. PhaseEvents are delivered to PhaseListeners at the beginning and end of each phase in the Faces lifecycle. These solutions do not include notification of other interesting events that occur during the processing of a Faces request.
JSF 2′s system events provide the ability to deliver SystemEvents to SystemEventListeners at arbitrary points during the request processing lifecycle. System events fall into two categories: global system events and component system events.
Global system events are delivered in response to application-wide activities, for example Application initialization/destruction. Listeners for these events are registered via a call to Application.subscribeToEvent().
Component system events are specific to individual component instances. For example, a component system event is delivered each time a component has been added to the view, or rendered, or validated. Component system event listeners are typically registered via a call to UIComponent.subscribeToEvent(). However, component system events also bubble up to the Application, where they are re-delivered to Application-level listeners. This allows global monitoring of component-related events.
Both global and component system events are fired by calling Application.publishEvent().
In order to simplify listener registration for component-specific events, JSF also provides a declarative listener registration solution via the
1
2
3
This registers the method located at #{bean.doSomePreValidation} as a pre-validation listener for the parent inputText component.
By providing notification of all sorts of activities that previously went undetected, system events open up many possibilities for page authors, component authors, framework authors and also for the JSF implementation itself!
Links
Issue 240 more events from the framework
Publish/Subscribe Event System
JSF 2 Gets Declarative Event Handling
SystemEvent (JavaDoc)
SystemEventListener (JavaDoc)
Application.subscribeToEvent() (JavaDoc)
UIComponent.subscribeToEvent() (JavaDoc)
Application.publishEvent() (JavaDoc)
Navigation
Implicit Navigation
In JSF 1.x, even the most trivial navigation cases required an entry in faces-config.xml. For example, when navigating from page1 to page2 in response to a “success” outcome on a command component in page1 required the following XML boilerplate code:
1
2
3
4
5
6
7
Fun stuff, right?
JSF 2.0 introduces a simplification that reduces navigation-related grunge code: implicit navigation. If no matching navigation case is found after checking all available rules, the navigation handler checks to see whether the action outcome corresponds to a view id. If a view matching the action outcome is found, an implicit navigation to the matching view occurs.
The end result: smaller faces-config.xml files. Oh, and happier JSF users.
Conditional Navigation
Another enhancement to the navigation subsystem is the addition of conditional navigation cases. The conditional navigation feature allows navigation cases to specify a pre-condition that must be met in order for the navigation case to be accepted. The pre-condition is specified as an EL expression using the new
1
2
3
4
5
6
7
8
One of the motivations behind this feature is to allow pre-conditions to be implemented in a loosely coupled, navigation-agnostic way. Instead of requiring a managed bean or business layer object return a navigation-centric outcome value, we can now use EL to interact with arbitrary properties/methods on these objects, freeing these objects from awareness of the JSF navigation system.
Preemptive Navigation
The JSF 1.x navigation system is a black box. The only entry point, NavigationHandler.handleNavigation(), simply evaluates the navigation rules and causes a navigation to occur, without giving any insight into how the navigation target is determined.
JSF 2.0 provides more transparent view of the navigation system. The new ConfigurableNavigationHandler API provides access to metadata describing the available navigation rules/cases. In particular, the getNavigationCase method allows clients to ask the ConfigurableNavigationHandler to determine which navigation case matches a particular outcome and from action. With this new contract, it is possible to “preemptively” evaluate navigation rules and retrieve the resulting target view id and URL.
Why is this interesting? Well, before JSF 2.0, navigation rules were explicitly the domain of POST requests. Previously, the only time that navigation rules came into play was during the invoke application phase while handling a POST. By making the navigation rules available outside of invoke application, we open up the possibility of leveraging this information at other points in the lifecycle, for example, during render response.
As we’ll see in the next topic, this has some interesting consequences relating to better support for GET-based navigation and bookmarkability, an area that has received much interest in recent years.
Links
Issue 179 Improve NavigationHandler API
Issue 419 outcome->viewId (was: Make navigation rules more flexible)
Issue 454 Decoupling navigation from the business layer
ConfigurableNavigationHandler (JavaDoc)
GET Support
It’s not so much that JSF 1.x does not provide any support for GET request handling… after all, there are some low-level primitives (like PhaseListeners) available. However, there is no denying that GET requests are a second-class citizen in earlier versions of the JSF specification. JSF 2.0 introduces several features that tackle this shortcoming.
View Parameters
The JSF 1.x specification goes to great lengths to provide a robust lifecycle for processing of values arriving from the client via Http requests. Values are pulled from the request, converted from strings to the proper target type, validated against application-specified constraints and finally, pushed into the model. Very powerful.
Of course, there is one caveat: all of this processing only applies to values arriving on POST requests. If the same value arrives via a GET request, well… tough luck! Or, well, maybe write a PhaseListener to manually process the request. Oh, and good luck reusing your converter/validator implementations to process those values!
JSF 2 brings some sanity to this situation with the introduction of “view parameters”, inspired by Seam’s page parameters. View parameters provide a simple, declarative way to map incoming request parameter values to any EL-reachable location. These mappings are specified using the new
1
2
3
The above sample specifies that the value of the request parameter with the name “foo” will automatically be picked off of the request and pushed into the property at #{bean.foo}. So if we receive a GET request as follows:
page1.jspx?foo=bar
The value #{bean.foo} property will be set to “bar” when JSF starts processing the request. No more need to manually code this sort of mapping in a PhaseListener. Yay!
But wait, there is more… The
PreRenderView Event
View parameters bring to GET requests much of the JSF request processing lifecycle that was formerly reserved for POSTs: request parameter decoding, type conversion, validation and model updates. But view parameters stop short of one last important step: invoking application-defined listeners. For this, system events come to the rescue.
JSF 2 includes a PreRenderViewEvent that is fired after view parameters have finished processing, but before the view is rendered. The pre-render view listener can be registered using the
1
2
3
4
This listener might be used to load data or set up context that is required prior to rendering. In addition, the listener may choose to programmatically navigate away from the requested view in the event that some pre-condition is not met (eg. the user does not have access to the requested page).
With the addition of view parameters and the pre-render view event, the GET request processing lifecycle is finally on par with the rich lifecycle provided for POSTs.
Now that we have the ability to respond to GET requests more effectively, what about the flip side? How do we issue these GET requests in the first place? Looking at the JSF 1.x components,
JSF 2 includes two new components that simplify GET-centric navigation:
1
Preemptive navigation is used to translate this logical outcome into a physical destination. At render time, the navigation system is consulted to map the outcome to a target view id, which is then transparently converted into the destination URL. This frees the page author from having to worry about manual URL construction.
Note that the URL construction process is not solely based on the target view id. The
1
The view parameters specified by the destination view are taken into account when building up the URL – ie. an inverse mapping of the view parameters is applied. Each view parameter value is extracted from the location specified by its EL expression, converted to a string, and added to the query string under the view parameter’s name.
This provides a simple yet powerful mechanism inserting required parameters into the query string. It also provides a nice technique for transferring request-scope data across requests.
In addition, page authors may manually insert query parameters using the
1
2
3
And of course, the key benefit of this solution: the resulting URLs are bookmarkable!
Links
Issue 487 Add navigation controls
JSF 2.0 – Bookmarkability/View Parameters
PreRenderViewEvent (JavaDoc)
Scopes
View Scope
View scope is one of two new scopes introduced in JSF 2 that fall into the category of “longer than request, shorter than session” scopes. As the name implies, state that is placed into view scope is preserved until the user finishes interaction with the current view. If you have ever had the joy of trying to figure out why your command component isn’t firing after binding the rendered attribute to a request-scoped managed bean, view scope may just be the answer to your problems.
View scope state can be accessed programmatically via UIViewRoot.getViewMap(). EL access is available via the #{viewScope} implicit object.
Flash Scope
JSF 2 borrows a concept from Rails with the introduction of the new flash scope. Flash scope provides a short-lived conversation. State that is placed into flash scope is propagated across a single view transition, including surviving redirects, and is cleaned up before moving on to yet another view. If you have been resorting to session scope to store state that needs to survive a redirect, flash scope might just be for you.
Flash scope state can be accessed programmatically via the ExternalContext.getFlash() API. EL access is available via the #{flash} implicit object.
Custom Scopes
JSF 2 also provides a small enhancement to the managed bean system to allow faces-config.xml authors to place managed beans into custom scopes. The trick is that custom scopes are specified via an EL expression rather than a keyword, eg:
1
2
3
4
5
The EL expression identifies the location of a map that holds the properties for the scope. When it is time to instantiate a custom-scoped managed bean, the managed bean system automatically pushes the new instance into the map under the specified name.
Links
Issue 140 Additional Scopes
Issue 290 UIViewScope – create a new scope, UIView
JSF 2.0 New Feature Preview Series (Part 5) EDR1 Potpourri Ryan’s introduction to view scope.
Bringing Ruby on Rails’s Flash to JSF 2006 article on Ed’s implementation of flash scope as a JSF extension.
Custom Managed Bean Scopes
CommandButton not calling action when using immediate and rendered“>
Configuration
Managed Bean Annotations
JSF 2 provides a long awaited usability improvement with the introduction of annotation-based configuration. The goal of these annotations is to reduce the size and complexity of faces-config.xml files, which have a tendency to get quickly out of hand. The first set of annotations allows developers to configure managed beans. The old style XML configuration:
1
2
3
4
5
Can now be replaced with annotations on the bean class:
1
@ManagedBean
2
@SessionScoped
3
public class Foo {
4
}
The name for the managed bean is automatically derived from the name of the annotated class. In the above example, the presence of @ManagedBean annotation on the Foo class makes a managed bean with the name “foo” available. Alternatively, the @ManagedBean annotation also allows a name to be specified explicitly.
Annotations are also available for the other scopes, as well as for managed properties.
Note: An effort is underway to unify these bean/scope annotations across specifications (eg. JSF, JCDI) for Java EE 6. In the meantime, the JSF 2 managed bean annotations are considered an optional part of the JSF 2 specification. Mojarra and MyFaces already provide implementations of these optional annotations.
Component Annotations
As part of the effort to prune down XML configuration bloat, JSF 2 also includes annotations targeted at authors of custom components (and associated objects). These annotations include:
@FacesComponent
@FacesRenderer
@FacesConverter
@FacesValidator
@FacesBehavior
Of course, the good old faces-config.xml elements are still present for those who prefer to go that route.
Faces-config.xml Ordering
A long-standing problem with faces-config.xml loading is that the order in which these files are loaded is unspecified. For the most part (eg. for managed bean or navigation configuration) the order is not significant. However, there are certain cases, such as decorating Application-level objects (eg. ViewHandlers), where the order may matter.
During the JSF 1.2 timeframe, both MyFaces and the JSF RI adopted a convention whereby faces-config.xml files are loaded based on an order derived from the containing jar file’s name. However, this was just a temporary implementation-level solution that was put in place until the issue could be addressed by the specification.
JSF 2 solves this problem by allowing faces-config.xml files to provide ordering-related hints. Each faces-config.xml file may now declare a name (via a new
This addition to the spec provides a much cleaner/safer way for the various frameworks/component sets to play together in the JSF ecosystem. No more jar file name hacking!
Project Stage
Project stage is a new configuration option that allows the application developer/deployer to specify a hint to the JSF implementation regarding the role of the current deployment. Valid values include:
Development
Production
SystemTest
UnitTest
This hint allows the JSF implementation to optimize its behavior for the current stage. For example, the JSF implementation might provide more verbose development-time diagnostics than would be practical for a production environment.
For a more specific example, check out the Mojarra team’s recent use of project stage to provide automatic compression of JSF’s own JavaScript library.
The project stage can be set either as a context parameter (“javax.faces.PROJECT_STAGE”) or via JNDI (“java:comp/env/jsf/ProjectStage”).
And, yes, my good friend and colleague Matthias Wessendorf would also like to see the project stage exposed as a system property.
Links
Issue 121 Require ordering of for loading META-INF/faces-config.xml files from component jar
Issue 287 ConfigAnnotations – Annotations to obviate faces-config.xml
Faces-config.xml? … We don’t need no stinkin’ faces-config.xml!
JSF Configuration Resource Ordering
JSF 2.0 New Feature Preview Series (Part 1): ProjectStage
Behaviors
The original JSF 1.0 specification introduced the concept of “attached objects” – ie. objects that are not UIComponents, but are attached to UIComponents in order to influence some aspect of the component’s behavior. This technique is used for conversion and validation by value holding components, eg:
1
2
3
JSF 2 adds a new class of attached object: the ClientBehavior. Whereas converters/validators focus on value processing, client behaviors assist in enhancing a component’s client-side functionality. Before client behaviors, page authors were forced to resort to hand-coding scripts and manually wiring these scripts up via event handling attributes, eg:
1
Client behaviors allow such scripts to be packaged up into reusable bundles that can be attached to components declaratively, eg:
1
2
3
This declarative approach is made possible by the introduction of two new contracts (along with various supporting APIs). The ClientBehavior contract specifies how client behavior implementations provide access to scripts and more generally how these objects participate in the component lifecycle. The ClientBehaviorHolder contract specifies how client behaviors are attached to components, similar to how EditableValueHolder specifies how converters and validators are attached.
In addition to defining these new contracts, JSF 2 also includes one concrete ClientBehavior implementation: the AjaxBehavior. The declarative form of this client behavior should be familiar from our earlier discussion on Ajax:
1
2
3
Although the JSF specification only defines a single concrete client behavior, the client behavior architecture is designed for extensibility. Expect to see plenty of third party client behavior implementations popping up!
Links
ClientBehavior (JavaDoc)
ClientBehaviorHolder (JavaDoc)
AjaxBehavior (JavaDoc)
Validation
Bean Validation
The Bean Validation JSR (JSR-303) defines a generic, tier-independent mechanism for specifying data validation constraints. The specification includes several standard constraint annotations (eg. @NotNull, @Size, @Min, @Max, etc…) and also allows custom constraints to be defined.
JSF 2 provides built-in integration with JSR-303 constraints. In environments where a bean validation implementation is present, JSF automatically validates constraints for beans that are referenced by UIInput values.
In addition,
1
2
3
When validation constraints fail, any associated error messages are automatically translated into FacesMessages by the JSF implementation, thus communicating the failures to the end user without placing any burden on the application developer.
Empty Field Validation
In previous JSF releases, Validators were not applied to EditableValueHolder components with null/empty submitted values. Unfortunately, this behavior limits the utility of constraints that actually check null/empty values, such as the JSR 303 @NotNull constraint. In order to support @NotNull and other similar constraints, JSF 2 changes the behavior of null/empty value validation. As of JSF 2, when a JSR-303 implementation is present, null/empty values are validated.
Since this may cause problems for legacy Validator implementations that do not expect to see null/empty values, the javax.faces.VALIDATE_EMPTY_FIELDS context parameter can be used to disable this behavior.
New Validators
In addition to
Links
Issue 426 Bean Validator support
Issue 480 Optionally validate all fields including those that are submitted empty
JSR 303 Bean Validation
Error Handling
JSF users who are new to Facelets will appreciate the more informative Facelets error page that provides information such as: line numbers! (And no, not just stack trace line numbers, but actual line numbers within the Facelets file.)
Of course, error pages are only useful in cases where the triggering exceptions are allowed to propagate up to the error handling layer and not pre-maturely consumed. The JSF 2 specification helps in this area with the introduction of the new ExceptionHandler API. JSF implementations are now required to allow all “unexpected” exceptions to propagate out of the current lifecycle phase so that they can be handled globally by an ExceptionHandler instance.
This change should reduce/eliminate those mysterious, hard to debug “swallowed” exceptions, as the ExceptionHandler now acts as a central clearing house for exceptions. Another advantage of this centralization is that it allows users/frameworks to devise more sophisticated error handling strategies.
ExceptionHandler (JavaDoc)
Resource Loading
If you spend time implementing custom JSF components of any complexity, eventually you are going to run into the question: what do I do with my component’s images (or JavaScript libraries, or style sheets)? Just about every JSF component framework has run into this problem and, in the absence of a standard solution, has solved this problem in its own proprietary way.
JSF 2 provides a standard solution to this problem with the introduction of the ResourceHandler API. The ResourceHandler is responsible for serving up resources (images, JavaScript files, style sheets, etc…) from well-known locations on the class path. Resource requests are routed through the FacesServlet, which passes these request onto the ResourceHandler for processing. This solution allows components and their resource dependencies to be bundled in the same jar file with no need for a bonus servlet, servlet filter or phase listener to serve up these artifacts.
JSF 2 also provides several new features in order to facilitate insertion of resource references. Authors of custom Java components can annotate their UIComponent subclasses with the @ResourceDependency annotation to identify any resources that need to be pulled in when the component is used. Composite component authors can use the new
The @ResourceDependency annotation and the
Note that in order to support resource relocation, JSF 2 introduces two other new components:
Links
JSF 2.0 New Feature Preview Series (Part 2.1): Resources
JSF 2.0 New Feature Preview Series (Part 2.2): Resources
JSF 2.0 New Feature Preview Series (Part 2.3): Resources
ResourceHandler (JavaDoc)
Tree Visiting
JSF 1.2 included the most useful addition of the UIComponent.invokeOnComponent() API. This provided the ability to invoke a callback on a single component instance in context. This functionality is particularly handy for any case where a single component (or subtree) needs to be targeted. (Think Ajax.)
While invokeOnComponent() is an excellent solution for the single component case, it is not particularly optimized for the multiple component case. If you need to target two components (eg. need to render two separate subtrees while processing an Ajax request), invokeOnComponent() will work, but requires two tree traversals in order to locate the two components. What happens if you need to render five separate subtrees? Or, even worse, what if you want to visit every component in context? Unfortunately invokeOnComponent() is not the answer.
JSF 2.0 solves the multi-component visiting case by introducing a sibling API to invokeOnComponent(): UIComponent.visitTree(). Both of these APIs traverse the component tree and invoke a callback on a subset of components. While invokeOnComponent() is designed to visit a single component, visitTree() may visit multiple components – and possibly all components – during its traversal. The set of components to visit is specified via a VisitContext that is passed into the visitTree() call.
While tree visiting is currently used under the covers by JSF implementations for features such as Ajax and state saving, the hope is that JSF frameworks/users will find other use cases where this new API proves helpful. If you currently have any case where you are calling invokeOnComponent() repeatedly (or are calling findComponent() when you should be calling invokeOnComponent()), be sure to check out the new tree visitor API!
Links
Issue 180 Tree Visitor Pattern
New Feature for JSF 1.2 (Jacob’s introduction to invokeOnComponent()
UIComponent.visitTree() (JavaDoc)
VisitContext (JavaDoc)
Conclusion
When I starting thinking about writing this article, I was hoping to provide a comprehensive overview of the entire JSF 2 feature set. As I got further into this undertaking, I realized that covering every single new feature/API in a single blog entry might be a bit, well… unwieldy. As such I decided to trim back my plans, but just slightly. There are a small number of minor API additions that I have not discussed here. Perhaps I’ll add a new section on these minor APIs at some point. For the moment, I am hoping that the information provided here is sufficiently complete to meet my original goal of providing a good introduction to the JSF 2 feature set.
If I have missed some feature/API that you think deserves discussion here, please leave a comment. Or if you know of other good sources of information, please leave a link. I am planning to update this blog from time to time with links to new blogs/articles as they become available, perhaps even to some that I write myself.
No comments:
Post a Comment