JSF 2.0 Features

Exclusive offer: get 50% off this eBook here
JSF 2.0 Cookbook

JSF 2.0 Cookbook — Save 50%

Over 100 simple but incredibly effective recipes for taking control of your JSF applications

$26.99    $13.50
by Anghel Leonard | June 2010 | Java Open Source Web Development

In this article by Anghel Leonard, author of the book JSF 2.0 Cookbook, we will cover the following features of JSF 2.0:

  • JSF 2.0 annotations
  • The JSF 2.0 exception handling mechanism
  • Bookmarking JSF pages with PrettyFaces

(For more resources on JSF, see here.)

JSF 2.0 annotations

One of the most important and useful features of JSF 2.0 consists in annotations. Based on them, JSF 2.0 provides an easy way to accomplish important tasks. In this recipe, we will present the most commonly used annotations and we will see what they can do for us.

How to do it...

If you are a JSF 1.2 fan, then you are familiar with the faces-config.xml configuration file. Starting with JSF 2.0, the content of this descriptor can be partially (sometimes totally) replaced with annotations.

Annotations for managed beans

The most common case is represented by the managed bean, which can be annotated as shown, instead of placing a specific declaration in faces-config.xml:


import javax.faces.bean.ManagedBean;

@ManagedBean
public class MyBean {
...
}

In the previous example, the bean is referenced as myBean, but you may specify another name, as shown next:

@ManagedBean(name="coolBean")

And what is a managed bean without a context (a scope)? JSF 2.0 supports an entire list of scope annotation, as shown next:

Annotation

Annotation Class

@RequestScoped

javax.faces.bean.RequestScoped

@SessionScoped

javax.faces.bean.SessionScoped

@ApplicationScoped

javax.faces.bean.ApplicationScoped

@ViewScoped

javax.faces.bean.ViewScoped

@NoneScoped

javax.faces.bean.NoneScoped

@CustomScoped(value="#{someMap}")

javax.faces.bean.CustomScoped

In addition, we can annotate a managed bean's properties using the @ManagedProperty annotation . The presence of this annotation on a field of a class annotated with @ManagedBean instructs the system to inject a value into this property:

@ManagedProperty("fooval")
private String foo;

@ManagedProperty("#{fooval}")
private String foo;

Going further, you can react to the creation and the destruction of a managed bean, as shown next:

public class MyBean {

@PostConstruct
public void postCreate(){
...
}

@PreDestroy
public void preDestroy(){
...
}

If you use JSF inside of a JEE container you can inject resources, session, message-driven beans, and web services into your managed beans. Something like the following is perfectly legal:

@ManagedBean
@SessionScoped
public class MyBean implements Serializable {

@EJB
private Facade facade;
...

@ResourceDependency annotation

JSF 2.0 specification has added the @ResourceDependency annotation to allow component authors to declare the resources the component will need. For example:

@ResourceDependency(name="my.css",library="libus")
public class MyComponent extends UIComponentBase {
...
}

You may use more than one @ResourceDependency using the @ResourceDependencies annotation, as the following:

@ResourceDependencies({ @ResourceDependency(name="my.
css",library="libus"),
@ResourceDependency(name="my.js",library="libus",target="head")
})
public class MyComponent extends UIComponentBase {
...
}

Now the components can be used without any knowledge about any of the CSS or JS code. The necessary dependencies will be rendered automatically.

The @ListenerFor annotation

A component will be annotated with the @ListenerFor annotation to indicate that it is subscribing to a particular set of events. Therefore, we will have two renderers that act as listeners for particular events and that implement the ComponentSystemEventListener interface (a detailed description of this interface is available at http://blogs.sun.com/ rlubke/entry/jsf_2_0_new_feature1, but as a quick description, system events are new in JSF 2.0, and there are system events that are global and others that are related to a component. They are created at various moments of application or request lifetime).

Let's see what this looks like:

@ListenerFor(systemEventClass=AfterAddToParentEvent.class,
sourceClass=UIOutput.class)
public class MyRenderer extends Renderer implements
ComponentSystemEventListener {
...
public void processEvent(ComponentSystemEvent event) throws
AbortProcessingException {
UIComponent component = event.getComponent();
FacesContext context = FacesContext.getCurrentInstance();
String target = (String)component.getAttributes().get("target");
if (target != null) {
context.getViewRoot().addComponentResource(context,
component, target);
}
}
...
}

There is also a plural version, named @ListenersFor.

There is one more annotation in which we are interested, named @NamedEvent, which will be discussed in the JSF declarative event handling recipe.

How it works...

Annotations for managed beans

Once you have annotated a class as a managed bean, it can be referred to as a bean with #{beanName.foo}, where beanName is class name (except packages) with the first letter changed to lower case, and "foo" is either an exact method name or a shortcut for a getter and setter method.

Regarding managed beans scopes we have:

@RequestScope: (this is the default scope of a managed bean). This puts the bean in request scope. It makes a new instance for every HTTP request. Commonly, the bean is instantiated twice, once when form is displayed and once when it is submitted.

@SessionScope: This puts a Serializable bean in session scope. When the same user with the same cookie returns then the same bean instance is used (for this, the session timeout should not be expired).

@ApplicationScoped: This puts the bean in application scope. All users will have access to this bean, therefore the bean either should have no state or you must manually and carefully synchronize access to it.

@ViewScoped: This puts the bean in view scoped. The same bean instance is used as long as the same user is on same page (for example, with AJAX).

@CustomScope: This puts the bean in custom scope. The bean is stored in the Map, and the developer can control its lifecycle.

@NoneScope: The bean is not put in a scope. Commonly these beans are referenced by other beans that are in scopes.

@ViewScoped, @CustomScoped and @NoneScoped are available only in JSF 2.0.

@ResourceDependency annotation

Once a component is created, it will be added as a child to another component. Before returning from the add() method, the component will be checked for @ResourceDependency annotations (both versions). When the @ResourceDependency is found a new UIOutput component instance is created. The ResourceHandler is queried for an appropriate Renderer based on the content type of the resource. In our case this is text/css, therefore the style sheet renderer will be used as the Renderer for this UIOutput component.

The values of the name, library (optional), and target (optional) attributes from the annotation are stored in the component's attribute map. UIViewRoot. addComponentResource() is called passing in the UIOutput and the value of the target attribute from the annotation (if exists).

Now when we render the view, for the head renderer we encode each of the resources that have been targeted for the head, like so:

...
UIViewRoot viewRoot = context.getViewRoot();
for (UIComponent ui_comp:viewRoot.getComponentResources(context,
"head")) {ui_comp.encodeAll(context);}
...

The @ListenerFor annotation

When the Renderer for this component is obtained it is queried for @ListenerFor annotations. For each annotation, the Renderer will be added as a component listener for the corresponding event. Going further, when the component is added in the tree, the event is invoked and the processEvent method will be called for adding the component as a resource to the VewRoot with the corresponding target.

JSF 2.0 Cookbook Over 100 simple but incredibly effective recipes for taking control of your JSF applications
Published: June 2010
eBook Price: $26.99
Book Price: $44.99
See more
Select your format and quantity:

(For more resources on JSF, see here.)

The JSF 2.0 exception handling mechanism

In this recipe we talk about the exception handling mechanism provided by JSF 2.0. You will see how to map exceptions to error pages in the web.xml file, how to use a managed bean for extracting an exception from the request and build a String from the stack trace, and how to customize the exception handling with a user-defined exception handler.

How to do it...

We start our recipe with the simplest solution for handling exceptions. It consists in mapping exception to error pages in the web.xml descriptor . For start we add in web.xml an entry for to define a JSF page as an error page (in our example, we define an error page named error.xhtml, mapped to the java.lang.NumberFormatException exception):

...
<error-page>
<exception-type>java.lang.NumberFormatException</exception-type>
<location>/faces/error.xhtml</location>
</error-page>

...

Now, JSF keeps track of a set of values in the request that provide more details on the error page. Next you can see one of these values edited in error.xhtml:

...
User Error:
#{requestScope['javax.servlet.error.message']}
...

Now, we can test the previous example by throwing a java.lang.NumberFormatException from a bean getter method, as shown next (when the error is thrown, the error.xhtml error page is getting into action):

...
private String number = "345s";
...
public String getNumber() {
try {
Integer intnumber = Integer.valueOf(this.number);
return String.valueOf(intnumber);
} catch (NumberFormatException e) {
throw new java.lang.NumberFormatException(e.getMessage());
}
}

public void setNumber(String number) {
this.number = number;
}
...

Going further, we can write a managed bean for extracting the exception from the request and building a String from the stack trace. You can see the action that does this job for us next:

...
private String error = "";
...
public String getError() {
StringBuilder errorMessage = new StringBuilder();
FacesContext facesContext = FacesContext.getCurrentInstance();
Map<String, Object> map =
facesContext.getExternalContext().getRequestMap();
Throwable throwable = (Throwable)
map.get("javax.servlet.error.exception");

if (throwable != null) {
errorMessage.append(throwable.getMessage()).append("\n");
for (StackTraceElement element : throwable.getStackTrace())
{
errorMessage.append(element).append("\n");
}
}
this.error = errorMessage.toString();
return this.error;
}
...

To get the stack trace we use the following code in the error.xhtml page:

...
System Administrator Error: <br/>
<h:outputText value="#{bean.error}"/>
...

You can go even further and customize the exception handling. Any custom exception handler should be defined in faces-config.xml, as in the following example:

...
<factory>
<exception-handler-factory>
exception.handler.CustomExceptionHandler
</exception-handler-factory>
</factory>
...

In the custom exception handler you should override the handle method to describe the behavior of your application in the case of a particular exception or set of exceptions. The prototype of this method is:

public void handle() throws FacesException {
...//do your job here
super.handle();
}

How it works...

Basically, in all three cases described previously, the idea is the same. The exceptions are caught by the system and they are treated according to our desires. We can provide a simple error page, or we can get much deeper and exploit the exception's stack trace and create large logs with detailed information for users or for administrators.

Bookmarking JSF pages with PrettyFaces

In this recipe, we will explore an open source extension for JSF 1.0 and JSF 2.0 that enables creation of bookmarkable, pretty URLs. Its name is PrettyFaces and it includes some nice features, such as:

  • Page-load actions
  • Seamless integration with Faces navigation
  • Dynamic view ID assignment
  • Managed parameter parsing
  • Configuration-free compatibility with other JSF frameworks

Getting ready

We developed this recipe with NetBeans 6.8, JSF 2.0, and GlassFish v3. The JSF 2.0 classes were obtained from the NetBeans JSF 2.0 bundled library. In addition, we have used PrettyFaces, which provides support for JSF 2.0. You can download this distribution from http://ocpsoft.com/prettyfaces/.

First copy the PrettyFaces libraries into your application /WEB-INF/lib folder, and second, add into the web.xml descriptor the PrettyFaces filter, as shown next:

...
<filter>
<filter-name>Pretty Filter</filter-name>
<filter-class>com.ocpsoft.pretty.PrettyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>Pretty Filter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
...

Now, you are ready to use PrettyFaces into JSF applications.

How to do it...

PrettyFaces is able to work around URLs by reading a specific configuration file, named pretty-config.xml, which is responsible for mapping URLs to Faces Views. Such a file is listed next (this file is stored in the /WEB-INF folder):

<?xml version="1.0" encoding="UTF-8"?>
<pretty-config
xmlns="http://ocpsoft.com/prettyfaces-xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://ocpsoft.com/prettyfaces-xsd
http://ocpsoft.com/xml/ns/prettyfaces/pretty-1.0.xsd">

<url-mapping id="1">
<pattern> /say_hello_1 </pattern>
<view-id>faces/hello1.xhtml</view-id>
</url-mapping>

<url-mapping id="2">
<pattern> /say_hello_2 </pattern>
<query-param name="hello" decode="false">
#{bean.hello}
</query-param>
<view-id>faces/hello2.xhtml</view-id>
</url-mapping>

<url-mapping id="3">
<pattern> /say_hello_3 </pattern>
<query-param name="hello" decode="false">
#{bean.hello}
</query-param>
<action>#{bean.upperHello}</action>
<view-id>faces/hello2.xhtml</view-id>
</url-mapping>

<url-mapping id="4">
<pattern> /say_hello_4 </pattern>
<view-id>#{bean.beanURL}</view-id>
</url-mapping>

</pretty-config>

As you can see a pretty-config.xml file is made from a set of <url-mapping> tags . Each tag maps a URL and is uniquely identified by the id attribute. The body of <url-mapping> can contain the following elements:

<pattern>/.../.../#{someBean.paramName}</pattern>

The <pattern> tag is required and it specifies which URL will be matched. Any EL expressions #{someBean.paramName} found within the pattern will be processed as value injection. This tag must appear only once per <url-mapping> tag.

<query-param name="key">#{someBean.queryParamValue}</query-param>

The <query-param> tag is optional and it defines a managed query parameter of the form http://my.site.com/url?key=somevalue, where if the parameter exists, the value will be injected into the specified managed bean. The name attribute is required and its value is a string representing the request value key. This tag also supports an optional attribute, named decode, which can be true (default) or false and it indicates if this <query-param> will/ will not be URLDecoded. This tag can appear zero or more times per <url-mapping> tag.

JSF commandLink and AJAX <f:param> values are also covered by the <query-param> tag.

<view-id>#{someBean.methodName}<view-id>

The <view-id> tag specifies the JSF view ID displayed by this mapping. It can be provided by a bean method (in this case the method must return an object for which the toString method will return the view Id) or by a String value. This tag must appear only once per <url-mapping> tag.

The View ID may be any resource located within the current Servlet Context.

<action>#{someBean.methodName}</action>

The <action> tag specifies an action method to be called after URL parameters have been parsed and assigned into beans. This tag also supports two attributes: the phaseId attribute is optional and its value is a string indicating that this action should occur immediately after the specified phase (the default is after RESTORE_VIEW phase, but it can be RESTORE_VIEW, APPLY_REQUEST_VALUES, PROCESS_VALIDATIONS, UPDATE_MODEL_VALUES, INVOKE_ APPLICATION, RENDER_RESPONSE, or ANY_PHASE).

If the phase does not occur, neither will your action method. If ANY_PHASE is specified, the action method will fire on EVERY phase.

The second optional attribute is onPostback, which is a Boolean (default true). Set it to false if this action method should not occur on form postback. This tag can appear zero or more times per <url-mapping> tag.

Now, you can see all these elements in the previous pretty-config.xml file. Next, we have developed a page to show how to call different other pages through Pretty. This page is named index.xhtml and is listed next:

...
<h:body>
<!-- example 1 -->
<h:outputLink value="say_hello_1">
<h:outputText value="HELLO (example_1)."/>
</h:outputLink>
<br/>

<!-- example 2 -->
<h:outputLink value="say_hello_2?hello=Adrian">
<h:outputText value="HELLO (example_2)"/>
</h:outputLink>
<br/>

<!-- example 3 -->
<h:outputLink value="say_hello_3?hello=Adrian">
<h:outputText value="HELLO (example_3)"/>
</h:outputLink>
<br/>

<!-- example 4 -->
<h:outputLink value="say_hello_4">
<h:outputText value="HELLO (example_4)"/>
</h:outputLink>
<br/>

</h:body>
...

And the bean used in this example is:

package beans;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

@ManagedBean
@SessionScoped
public class Bean {
private String hello = "";

public Bean() {
}

public String getHello() {
return hello;
}

public void setHello(String hello) {
this.hello = hello;
}

public void upperHello() {
this.hello = this.hello.toUpperCase();
}

public String beanURL(){
return "/faces/hello3.xhtml";
}
}

Now when you try to bookmark a URL managed by PrettyFaces you can see the "pretty" URL is used instead of the "ugly" one!

How it works...

PrettyFaces makes use of its own filter to intercept URLs. Once it captures a URL it resolves it against the pretty-config.xml file by accessing the corresponding <url-mapping> tag. When we bookmark a page the <pattern> body is bookmarked and the real URL is hidden.

PrettyFaces also provides other facilities such as:

  • Using dynamic view ID capabilities
  • Using the Managed Query Parameter facility
  • Validating URL parameters
  • Wiring navigation into JSF action methods
  • Parsing complex / dynamic-length URLs
  • Accessing PrettyContext through EL
  • Rendering HTML links and URLs
  • Configuring logging (log4j)

More information about PrettyFaces is available at

http://ocpsoft.com/prettyfaces/docs/.

Summary

This article presented some of the most relevant JSF 2.0 features, such as annotations, exception handling mechanism, and bookmarking JSF pages with PrettyFaces.

In the next article, we will see some more features of JSF 2.0 such as, JSF declarative event handling, JSF view parameters, and so on.


Further resources on this subject:

JSF 2.0 Cookbook Over 100 simple but incredibly effective recipes for taking control of your JSF applications
Published: June 2010
eBook Price: $26.99
Book Price: $44.99
See more
Select your format and quantity:

About the Author :


Anghel Leonard

Anghel Leonard is a senior Java developer with more than 13 years of experience in Java SE, Java EE, and related frameworks. He has written and published more than 50 articles about Java technologies and more than 500 tips and tricks for many websites that are dedicated to programming. In addition, he has written the following books:

  • Tehnologii XML XML în Java, Albastra
  • Jboss Tools 3 Developer's Guide, Packt Publishing
  • JSF 2.0 Cookbook, Packt Publishing
  • JSF 2.0 Cookbook: LITE, Packt Publishing
  • Pro Java 7 NIO.2, Apress
  • Pro Hibernate and MongoDB, Apress

Currently, Anghel is developing web applications using the latest Java technologies on the market (EJB 3.0, CDI, Spring, JSF, Struts, Hibernate, and so on). Over the past two years, he's focused on developing rich Internet applications for geographic information systems.

Books From Packt


GlassFish Security
GlassFish Security

Apache MyFaces 1.2 Web Application Development
Apache MyFaces 1.2 Web Application Development

JavaFX 1.2 Application Development Cookbook
JavaFX 1.2 Application Development Cookbook

iReport 3.7
iReport 3.7

Amazon SimpleDB Developer Guide
Amazon SimpleDB Developer Guide

Oracle JRockit: The Definitive Guide
Oracle JRockit: The Definitive Guide

Spring Security 3
Spring Security 3

NetBeans Platform 6.9 Developer's Guide
NetBeans Platform 6.9 Developer's Guide


Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software