ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button O'Reilly Book Excerpts: JavaServer Faces

Handling Events in JavaServer Faces, Part 1

by Hans Bergsten

Editor's note: O'Reilly's JavaServer Faces offers developers a guide to learning how to use the JSF framework to build web applications. In this excerpt from the book, author Hans Bergsten looks at the JSF event model, using examples to help explain what's going on "under the hood." Next week, in part two of this excerpt, Hans implements event handling for parts of the sample application discussed here.

Related Reading

JavaServer Faces
By Hans Bergsten

Handling Events

When the user clicks a button or link, changes a value in a field, or makes a selection in a list, the application may need to react. JSF user interface components signal user actions by firing an event handled by application code that has registered itself to be notified of the event. It's a model borrowed from traditional GUI frameworks, making it easy to develop and maintain the code for each specific user action in a separate code module. You can even use multiple event handling modules for different aspects of the processing, such as one that logs the action and another that acts on it.

On the surface, the JSF model looks the same as the event model used for standalone applications, but there's a twist: with JSF, the user actions take place in a client (e.g., a browser) that has no permanent connection to the server, so the delivery of some types of event is delayed until a new connection is established (e.g., when the user submits a form). To deal with this difference, JSF defines a strict request processing lifecycle, where events are generated and handled in different phases.

In this chapter, we first look at the event model and how it relates to the request processing lifecycle to understand what's going on. We then implement event handling for parts of the sample application.

Understanding the JSF Event Model

The JSF event model is based on the event model defined by the JavaBeans specification. In this model, an event is represented by an instance of an event class. An event source object fires an event by calling an event notification method on event listener objects registered to receive the event, passing a reference to the event object as a notification method argument.

Let's look at what this means in more detail. All JSF event classes extend the javax.faces.event.FacesEvent class:

package javax.faces.event;

import java.util.EventObject;
import javax.faces.component.UIComponent;
...

public abstract class FacesEvent extends EventObject {
    public FacesEvent(UIComponent component) {
        super(component);
    }

    public UIComponent getComponent( ) {
        return ((UIComponent) getSource( ));
    }
    ...
}

The FacesEvent class extends the standard Java event superclass java.util.EventObject and has a constructor that takes the UIComponent event source object as an argument. It also implements a type-safe accessor method for the event source object.

When a user clicks a button, it triggers an event represented by the javax.faces.event.ActionEvent class:

package javax.faces.event;

import javax.faces.component.UIComponent;

public class ActionEvent extends FacesEvent {
    public ActionEvent(UIComponent component) {
        super(component);
    }
    ...
}

Other events are represented by similar concrete subclasses, such as the javax.faces.event.ValueChangeEvent, which signals a value change.

Along with the event classes, there are listener interfaces declaring the methods that the event source calls to notify listeners of the event. A listener interface can contain methods for many related events, but for the JSF component events, there's a separate interface per event. Here's the javax.faces.event.ActionListener interface:

package javax.faces.event;

import javax.faces.component.UIComponent;

public interface ActionListener extends FacesListener {
    public void processAction(ActionEvent event) 
        throws AbortProcessingException;
}

The ActionListener interface extends the javax.faces.event.FacesListener interface and defines one method, taking an ActionEvent instance as the single argument.

Classes that want to be informed about events are called event listeners. They declare which events they are interested in by implementing the corresponding listener interfaces. Hence, an event listener that wants to deal with the ActionEvent fired by a command component declares its intent like this:

package com.mycompany.expense.ui;

import javax.faces.event.ActionListener;

public class ReportHandler implements ActionListener {
    ...
    public void processAction(ActionEvent e) 
      throws AbortProcessingException {
        ...
    }
}

To prevent other listeners from seeing an event, all JSF event-processing methods can throw a javax.faces.event.AbortProcessingException. This is rarely needed, but can come in handy when serious problems occur while processing the event. If the event notification method throws this exception, JSF stops the event processing immediately.

Event source classes, like UICommand, declare the type of events they can fire by providing methods for registering and deregistering the corresponding event listeners:

    public void addActionListener(ActionListener listener) {
        addFacesListener(listener);
    }

    public void removeActionListener(ActionListener listener) {
        removeFacesListener(listener);
    }

The methods follow the JavaBeans conventions: the method names are made from the words add and remove followed by the listener interface name, and both methods take an instance of the listener as the single argument.

The addFacesListener() and removeFacesListener() methods called by the registration and deregistration methods are protected methods implemented by UIComponentBase, so that the task of maintaining the listener list doesn't have to be implemented by all subclasses.

When a component notices that a user event has happened, it creates an instance of the corresponding event class and adds it to an event list. Eventually, JSF tells the component to fire the event, i.e., loop through the list of listeners for that event and call the event notification method on each one.

Pages: 1, 2, 3

Next Pagearrow