Java Server Faces: Event Handling

1. EVENT HANDLING

In JSF event handling model, an event is represented by an instance of an event class. An event source generates an event which is then delivered to event listener objects registered to receive the event.

JSF supports three kinds of events: value-change events, action events and phase change events. A value-change event occurs when the user changes the value of components (such as uiinput,

UlSelectOne, UISelectMany, and UISelectBoolean), that implements EditableValueHolder interface. An action event occurs when the user performs some actions such as clicking on components (such as buttons or links) that implement ActionSource interface.

We can specify event listeners using either event attributes or event tags. When attribute is used, we implement a method in a backing bean to handle the event and refer that method in an EL expression from the appropriate attribute of the component. On the other hand, if the listener tag is used, we implement an event listener to handle the event and register the listener on a component by nesting a listener tag inside the UI component tag.

1.1. Value Change Listener

A value change listener can be implemented in two ways: Using valueChangeListener attribute of the component tag and using <f:valueChangeListener> tag

1.1.1. Using valueChangeListener Attribute

We first implement a method in a managed bean. The method should look like this:

public void methodName(ValueChangeEvent e);

Here is an example:

@ManagedBean(name = ”ehBean”) public class Bean {

public void valueChanged(ValueChangeEvent e) {

//take actions

}

}

We can write any code inside the method. This listener method can then be attached with a component using its vaiueChangeListener attribute as follows:

<h:form >

<h:inputText valueChangeListener=”#{ehBean.valueChanged}” onchange=”submit()”/>

</h:form>

The onchange attribute is used to make a JSF call when a value of the text box is changed. JSF runtime implementation then calls this vaiueChanged() method. Note that for components such as buttons or links, onchange attribute is not necessary. Also note that this method limits us to use only one listener for the component.

1.2. Using <f:valueChangeListener> tag

Here, we write a class that implements VaiueChangeListener interface that has single method public void processVaiueChange(). Here is a sample value change listener class:

package eh;

import javax.faces.event.*;

public class MyValueChangeListener implements VaiueChangeListener {

@Override

public void processValueChange(ValueChangeEvent event) throws AbortProcessingException {

//take actions

}

}

We can then attach this listener with a component as follows:

<h:form >

<h:inputText onchange=”submit()”>

<f:valueChangeListener type=”eh.MyValueChangeListener”/>

</h:inputText>

</h:form>

The type attribute specifies fully-qualified name of the listener class. When the value of the text box changes, the processVaiueChange() method of the listener gets called. This method allows us to attach more than one listener with a component.

3. Action Listener

An action listener may also be implemented in two ways: Using actionListener attribute of the component tag and using <f:actionListener> tag.

3.1. Using actioneListener Attribute

Here, we first implement a method in a managed bean. The method should look like this:

pubiic void methodName(ActionEvent e);

Here is an example:

@ManagedBean(name = ”ehBean”) public class Bean {

public void actionMethod(ActionEvent e) {

//take actions

}

}

We can write any code inside the method. This listener method can then be attached with a component using its actionListener attribute as follows:

<h:form >

<h:commandButton value=”Click” actionListener=”#{ehBean.actionMethod}”/>

</h:form>

When the button is clicked, the form is submitted which makes a JSF call. The JSF runtime implementation then calls this actionMethod() method. Note that this method limits us to use only one listener for the component.

1.4. Using <f:actionListener> tag

Here, we write a class that implements ActionListener interface that has single method public void processAction(). Here is a sample value change listener class:

package eh;

import javax.faces.event.*;

public class MyActionListener implements ActionListener {

@Override

public void processAction(ActionEvent event) throws AbortProcessingException{ //take actions

}

}

We can then attach this listener with a component as follows:

<h:form >

<h:commandButton value=”Click” >

<f:actionListener type=”eh.MyActionListener”/>

</h:commandButton>

</h:form>

The type attribute specifies fully-qualified name of the listener class. When the button is clicked, the processAction() method of the listener gets called. This methods allows us to attach more than one listeners with a component.

2. AN EVENT HANDLING EXAMPLE

In the previous sections, we have seen how to work with JSF events. Let us now write a simple application that leverages JSF’s event model. The application has a simple xhtml file containing two selection boxes. The first one has a list of components (such as HDD, Monitor etc.) present in a computer system. The purpose of the second selection box is to provide a set of options for the component selected. This requires the content of the second selection box to be changed when a user selects a component from the first one. Here is the relevant part of the xhtml file:

<h:form>

Select component:

<h:selectOneMenu onchange=”submit()” valueChangeListener=”#{ehMyBean.set}” >

<f:selectItems value=”#{ehMyBean.items}” />

</h:selectOneMenu>

Size:

<h:selectOneMenu >

<f:selectItems value=”#{ehMyBean.spec}” />

</h:selectOneMenu>

</h:form>

The backing bean is shown here:

package eh;

import java.util.*;

import javax.faces.bean.*;

import javax.faces.event.*;

@ManagedBean(name = ”ehMyBean”, eager = true)

@SessionScoped public class MyBean {

Map<String, String[]> maps = new LinkedHashMap<String,String[]>();;

String[] spec;

public MyBean(){

maps-put(“HDD”, new String[] {”200 GB”, ”500 GB”});

maps.put(”Monitor”, new String[] {”20’”, ”21’”});

spec = maps.get(”HDD”);

}

public void set(ValueChangeEvent e){

spec = maps.get(e.getNewValue());

}

public String[] getSpec() { return spec; }

public Object[] getItems(){

return maps.keySet().toArray();}

}

A sample screen shot of this application is shown here:

Source: Uttam Kumar Roy (2015), Advanced Java programming, Oxford University Press.

Leave a Reply

Your email address will not be published. Required fields are marked *