5 min read

(For more resources on JSF, see here.)

JSF declarative event handling

Starting with JSF 2.0 the event system has been really improved and the declarative event handling is exposed through a tag, f:event, and an annotation, @NamedEvent. In this recipe, you will see how to work with these two and how to subscribe to events like preRenderComponent, PostAddToView , and so on.

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.

How to do it…

Starting with the f:event tag, we can say that this is a simple tag that should be fitted in the right place and configured with its two simple attributes. Speaking of fitting it in the right place, you should know that f:event can be placed in any component that you want—for example we put it in an h:inputText component:

<h:inputText value="#{bean.number}">
<f:event type="preRenderComponent"
listener="#{bean.initNumber}" />
</h:inputText>
...

As you can see there are two attributes of the f:event tag , named type and listener. The value of the type attribute represents the name of the event for which to install a listener (in our example, we have used the preRenderComponent value—with other words, before the component is rendered). In the following table are the possible values, and the corresponding event type for which the listener action is registered.

Value for type attribute

Type of event sent to listener method

preRenderComponent

javax.faces.event.PreRenderComponentEvent

postAddToView

javax.faces.event.PostAddToViewEvent

preValidate

javax.faces.event.PreValidateEvent

postValidate

javax.faces.event.PostValidateEvent

The listener attribute’s value represents a MethodExpression pointing to a method that will be called when the listener’s processEvent method would have been called. In our example, that method is named initNumber and it can be seen in the following managed bean:

package beans;

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

@ManagedBean
@SessionScoped
public class Bean {

private String number = "";

public Bean() {
}

public String getNumber() {
return number;
}

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

public void initNumber(){
setNumber("2010");
}
}

While f:event works only with predefined events, the @NamedEvent provides support for exposing custom events. The application developer can make a custom event available to the page authors using the @NamedEvent annotation . This annotation can be placed on custom events to register them with the runtime, making them available to f:event. When the application starts, JSF scans for a set of annotations, including @NamedEvent. If it is found on a class, the following logic is applied to get the name/names for the event:

  1. Get the unqualified class name
  2. Cut off the trailing “Event”, if present
  3. Convert the first character to lower-case
  4. Prepend the package name to the lower-cased name

The preceding four rules are ignored if the shortName attribute is specified. In this case JSF registers the event by that name.

URLs based on specified navigation outcome

One of the most requested features in JSF 2.0 was a nice and smooth mechanism for achieving bookmarkability of JSF pages. As you will see in this recipe, this mechanism is finally provided by JSF 2.0 and is a very robust and easy-to-use solution.

Getting ready

We have 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.

How to do it…

Now, let’s get into the subject, and let’s say that the JSF 2.0 bookmarkability mechanism is based on two new tags, named h:link and h:button. These tags will generate a URL based on the specified navigation outcome.

In JSF 2.0, we can make use of implicit navigation, therefore the outcome can be defined in the view or using common navigation rules.

OK, enough theory, let’s see an example:

...
<h:link outcome="page2" value="HelloToYou">
<f:param name="helloparam" value="#{bean.hello}"/>
</h:link>
...

In the previous example, we assume no navigation rule, therefore the outcome attribute indicates a navigation to page2.xhtml (the FacesServlet is mapped to *.xhtml). The value attribute indicates text that will be rendered as a link in the page. The f:param will add a query parameter to the generated URL. The result of this component will be:

http://localhost:8080/ URLs_based_on_specified_navigation_outcome/ faces/page2.xhtml?helloparam=Adrian

The Adrian value comes from a simple managed bean:

package beans;

import javax.enterprise.context.RequestScoped;
import javax.faces.bean.ManagedBean;

@ManagedBean
@RequestScoped
public class Bean {

private String hello = "Adrian";

public Bean() {
}

public String getHello() {
return hello;
}

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

You can bookmark this page at any moment and conserve the URL. The h:button works in the same manner except that it renders a button instead of a link.

How it works…

Before the user uses the component—clicks on the hyperlink—the current view ID and the specified outcome are used to find the target view ID. Afterwards, it is translated into a bookmarkable URL and used as the hyperlink’s target. Note that this is true even if the user never activates the component.

The target view ID is placed in the attribute named outcome on the new bookmarkable component tags, h:link or/and h:button (those components inherit from a component class named UIOutcomeTarget). Notice that you are not targeting a view ID directly, but rather a navigation outcome, which may be interpreted as a view ID if the matching falls through to implicit navigation.

We consider that this is a good place and time to point out some methods of creating the query string parameters, therefore we present them in the order that they are processed:

  1. Implicit query string parameter
  2. View parameter (the <f:metadata> of the target view ID)
  3. Nested <f:param> in UIOutcomeTarget (such as, <h:link>)
  4. Nested <view-param> in the navigation case <redirect> element in facesconfig.xml

LEAVE A REPLY

Please enter your comment!
Please enter your name here