Writing the ActionListener for the Listener and Component Tree Example
The ActionListener for the command button is the most interesting part of this JSF application. It demonstrates how an event causes a listener to be executed. The listener simply prints messages to the console. However, it shows important information such as the hierarchy of the component tree of the JSP page from which the event was fired and the component that triggered the event. The ActionListener is shown in Listing 5.
Listing 5 The ActionListener for the Command Button (MyActionListener.java)
[code]
package ch02a;
import java.util.Iterator;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.event.ActionListener;
import javax.faces.event.PhaseId;
import javax.faces.tree.Tree;
public class MyActionListener implements ActionListener {
public PhaseId getPhaseId() {
System.out.println(“getPhaseId called”);
return PhaseId.APPLY_REQUEST_VALUES;
}
public void processAction(ActionEvent event) {
System.out.println(“processAction called”);
// the component that triggered the action event
UIComponent component = event.getComponent();
System.out.println(
“The id of the component that fired the action event: ”
+ component.getComponentId());
// the action command
String actionCommand = event.getActionCommand()
System.out.println(“Action command: ” + actionCommand);
FacesContext facesContext = FacesContext.getCurrentInstance();
Tree tree = facesContext.getTree();
UIComponent root = tree.getRoot();
System.out.println(“———– Component Tree ————“);
navigateComponentTree(root, 0);
System.out.println(“—————————————-“);
}
private void navigateComponentTree(
UIComponent component, int level){
// indent
for (int i=0; i<level; i++)
System.out.print(” “);
// print component id
System.out.println(component.getComponentId());
Iterator children = component.getChildren();
// navigate children
while (children.hasNext()) {
UIComponent child = (UIComponent) children.next();
navigateComponentTree(child, level + 1);
}
}
}
[/code]
![]() Buy this book! |
{mospagebreak title=The Action Listener}
An ActionListener must implement the javax.faces.event.ActionListener interface. It provides the implementations for the getPhaseId and processAction methods. The getPhaseId method must return a javax.faces.event.PhaseId, and its return value determines in which process event step of the request processing lifecycle the listener will be executed. The getPhaseId method in the ActionListener in Listing 5 returns PhaseId.APPLY_REQUEST_VALUES. This will make the ActionListener‘s processAction method be called after the Apply Request Values phase of the request processing lifecycle.
The processAction method accepts the javax.faces.event.ActionEvent object from the Lifecycle object. In the ActionListener in Listing 5, the processAction method first obtains the component that triggered the event by calling the getComponent method of the ActionEvent class, and then it prints the component identifier.
[code]
UIComponent component = event.getComponent();
System.out.println(
“The id of the component that fired the action event: “
+ component.getComponentId());
[/code]
It then prints the action command of the ActionEvent object.
[code]
// the action command
String actionCommand = event.getActionCommand();
System.out.println(“Action command: ” + actionCommand);
[/code]
Next, it obtains the instance of the current FacesContext and calls its getTree method to acquire the component tree (an instance of javax.faces.tree.Tree class) representing the request page.
Tree tree = facesContext.getTree();
[/code]
[code]navigateComponentTree(root, 0);[/code]
![]() Buy this book! |
{mospagebreak title=Continuing With the navigateComponent Tree}
The navigateComponentTree method is called recursively. It first prints the identifier of the component passed in to it. The identifier is indented by a number of blank spaces proportionate to the level argument. The level argument determines the number of spaces before the component name. The indention gives the effect of a hierarchy. When called from the processAction method, the navigateComponentTree method is passed 0 as the level argument.
[code]
for (int i=0; i<level; i++)
System.out.print(” “);
// print component id
System.out.println(component.getComponentId());
[/code]
The navigateComponentTree method then obtains the children of the passed in component by calling the getChildren method of the UIComponent interface. The getChildren method returns an Iterator containing all children of the component.
[code]
Iterator children = component.getChildren();
[/code]
Next, it iterates all the children and calls the navigateComponentTree method for each of the component’s children.
[code]
while (children.hasNext()) {
UIComponent child = (UIComponent) children.next();
navigateComponentTree(child, level + 1);
}
}
Compiling and Running the Listener and Component Tree Example
jar;../../../../common/lib/servlet-api.jar ch02a/*.java[/code]
Note that to compile the source files, you need two library files in the lib directory and the servlet-api.jar file. In Tomcat 5, the servlet-api.jar file can be found in the common/lib directory of Tomcat’s home directory.
If you are using Linux/Unix, use colons (rather than semicolons) to separate the library files:
javac -classpath ../lib/jsf-api.jar:../lib/jsfri.
jar:../../../../common/lib/servlet-api.jar ch02a/*.java
[/code]
Then run Tomcat. You can then direct your browser to the following URL:
http://localhost:8080/JSFCh02a/faces/adder.jsp
[/code]
![]() Buy this book! |
{mospagebreak title=Console Message}
And, in the console, you will see the following message:
Model Object Created
getFirstNumber:0
getSecondNumber: 0
getResult: 0
getPhaseId called
Viewing the source, you can see the following HTML tags:
[code]
<html>
<head>
<title>Add 2 numbers</title>
</head>
<body>
<form method=”post”
action=”/JSFCh02a/faces/adder.jsp;jsessionid=
1EF862DDA5B0B99F69E73A32F417552B”>
<br/>First Number:
<input type=”text” name=”firstNumber”
id=”firstNumber” value=”0″/>
<br/>Second Number:
<input type=”text” name=”secondNumber”
id=”secondNumber” value=”0″/>
<br/>Result:
0
<br/>
<input type=”submit” name=”submitButton”
value=” Add ”/>
</form>
</body>
</html>
[/code]
Figure 6 Running the application
![]() Buy this book! |
{mospagebreak title= And the Message}
More informative is the message that is displayed in the console:
getFirstNumber: 0
getSecondNumber: 0
processAction called
The id of the component that fired the action event: submitButton
Action command: submit
———– Component Tree ————-
null
addForm
firstNumber
secondNumber
output
submitButton
—————————————-
setFirstNumber: 10
setSecondNumber: 20
getFirstNumber: 10
getSecondNumber: 20
getResult: 30
Creating the Validator Example
The example presented in this section demonstrates how you can validate user input very easily in JSF. This application is even simpler than the one presented in the previous section. It consists of only one JSP page, and it does not require a JavaBean or an application configuration file. However, you will still need a directory structure for the application and the deployment descriptor. The deployment descriptor is the same as the one in Listing 1. Here, we will look at the directory structure and JSP page.
Creating the Directory Structure for the Validator Example
The directory structure for your application, called JSFCh02b, is depicted in Figure 8. In Tomcat, you create this under webapps. The directory contains all the required components that you will build in this example.
Again, you must copy the .jar files containing the JSF implementation into the WEB-INF/lib directory. Then, in the application directory, you have the validatorTest.jsp page.
![]() Buy this book! |
{mospagebreak title=Authoring the JSP Page for the Validator Example}
The JSP page is the only component in this application. It is called validatorTest.jsp and is shown in Listing 6.
Listing 6 The validatorTest.jsp Page
[code]
<%@ taglib uri=”http://java.sun.com/jsf/html” prefix=”h” %>
<%@ taglib uri=”http://java.sun.com/jsf/core” prefix=”f” %>
<html>
<head>
<title>Validator Test</title>
</head>
<body>
<f:use_faces>
<h:form formName=”myForm”>
Enter a minimum of 6 characters here:
<h:input_text>
<f:validate_length minimum=”6″/>
</h:input_text>
<br/>
<h:command_button label=”Submit” commandName=”submit”/>
<br/>
<h:output_errors/>
</h:form>
</f:use_faces>
</body>
</html>
[/code]
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %><%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>The validatorTest.jsp page contains a form with a UIInput component represented by the input_text custom tag. The form also contains a command_button tag representing a UICommand, as well as an output_errors tag for displaying any error that occurs during processing. The most important part is the validate_length tag inside the input_text tag.
[code]
<h:input_text>
<f:validate_length minimum=”6″/>
</h:input_text>
[/code]
Figure 8 The directory structure for the validator example
The validate_length tag represents one of the standard validators in JSF. It checks for the length of the input and makes sure that it has a minimum of six characters. Any input shorter than six characters will generate an error that will be displayed by the output_errors tag.
Running the Validator Example
To run the application, you need to restart Tomcat. Then, use the following URL to invoke the validatorTest.jsp page:
http://localhost:8080/JSFCh02b/faces/validatorTest.jsp
Figure 9 shows the error message displayed for an input value shorter than six characters.
Figure 9 The validator example in action
![]() Buy this book! |