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

advertisement

AddThis Social Bookmark Button

Introducing JavaServer Faces
Pages: 1, 2

Authoring the JSP Page

A JSP page called adder.jsp provides the user interface, as seen in Listing 2.



Listing 2. The adder.jsp page

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<html>
<head>
<title>Add 2 numbers</title> 
</head>
<body>
<jsp:useBean id="NumberBean" class="jsfApp.NumberBean" scope="session" />
<f:use_faces><br />
    <h:form id="addForm" formName="addForm" ><br />
        First Number:<br />
        <h:input_number id="firstNumber" valueRef="NumberBean.firstNumber" /><br />
        Second Number: 
        <h:input_number id="secondNumber" valueRef="NumberBean.secondNumber" /><br />
        Result: 
        <h:output_number id="output" valueRef="NumberBean.result"/><br>
        <h:command_button id="submitButton" label="Add" commandName="submit" >
            <f:action_listener type="jsfApp.MyActionListener" />
        </h:command_button>
    </h:form>
</f:use_faces>
</body>
</html>

We first define two taglib directives to use the two JSF tag libraries, html and core. The tag library descriptors for these two libraries can be found in the jsf-ri.jar file, so you don't have to worry about them. Their prefixes are h and f, respectively.

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>

The <jsp:useBean> action element defines the NumberBean JavaBean with a session scope.

<jsp:useBean id="NumberBean" class="jsfApp.NumberBean" scope="session" />

Next come the JSF controls. Note that JSF controls must be enclosed in the <f:use_faces> opening and closing elements:

<f:use_faces>
...
</f:use_faces>

Inside them, you have a form.

<h:form id="addForm" formName="addForm">
...
</h:form>

Nested inside of the form are two input_numbers, an output_number, and a command_button.

First Number:
<h:input_number id="firstNumber" valueRef="NumberBean.firstNumber" /><br />
Second Number: 
<h:input_number id="secondNumber" valueRef="NumberBean.secondNumber" /><br />
Result: 
<h:output_number id="output" valueRef="NumberBean.result" /><br />
<h:command_button id="submitButton" label="Add" commandName="submit">
    <f:action_listener type="jsfApp.MyActionListener" />
</h:command_button>

Notice the action listener for the command button? Figure 2 depicts the component tree for this JSP page, with the root omitted.

the component tree of the adder page
Figure 2. The component tree of the adder.jsp page

The main component is the form, which has four child components.

Writing the Object Model

For this application, you need a JavaBean to store the two numbers to add and the result of the addition. Listing 3 presents this JavaBean, NumberBean.

Listing 3. The NumberBean JavaBean

package jsfApp;
public class NumberBean {
    int firstNumber  = 0;
    int secondNumber = 0;

    public NumberBean () {
        System.out.println("Creating model object");
    }

    public void setFirstNumber(int number) {
        firstNumber = number;
        System.out.println("Set firstNumber " + number);
    }

    public int getFirstNumber() {
        System.out.println("get firstNumber " + firstNumber);
        return firstNumber;
    }

    public void setSecondNumber(int number) {
        secondNumber = number;
        System.out.println("Set secondNumber " + number);
    }

    public int getSecondNumber() {
        System.out.println("get secondNumber " + secondNumber);
        return secondNumber;
    }

    public int getResult() {
        System.out.println("get result " + (firstNumber + secondNumber));
        return firstNumber + secondNumber;
    }
}

Writing the Action Listener

The action listener for the command button is the most interesting part of this JSF application. It demonstrates how an event causes a listener to execute. 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. Listing 4 shows the action listener.

Listing 4. The action listener for the command button (MyActionListener.java)

package jsfApp;

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) {
        Iterator children = component.getChildren();

        // indent
        for (int i=0; i<level; i++)
            System.out.print("  ");

        // print component id
        System.out.println(component.getComponentId());

        // navigate children
        while (children.hasNext()) {
            UIComponent child = (UIComponent) children.next();
            navigateComponentTree(child, level + 1);
        }
    }
}

Compiling and Running the Application

To compile the application, change to the myJSFApp/WEB-INF/classes directory. If you are using Windows, type the following command:

$ javac -classpath ../lib/jsf-api.jar;../lib/jsf-ri.jar; \
    ../../../../common/lib/servlet.jar jsfApp/*.java

Note that you need to use library files in the lib directory and the servlet.jar file. In Tomcat, the servlet.jar file can be found in the common/lib subdirectory of Tomcat's home directory.

If you are using Linux or Unix, change the semicolons that separate library files to colons:

$ javac -classpath ../lib/jsf-api.jar:../lib/jsf-ri.jar: \
    ../../../../common/lib/servlet.jar jsfApp/*.java

Then run Tomcat. You can then direct your browser to the following URL:

http://localhost:8080/myJSFApp/faces/adder.jsp

Note that you use the /faces/ pattern before the JSP page name. You will see something similar to Figure 3 in your browser.

running the application
Figure 3. Running the application

In the console, you'll see the following message:

Model Object Created
get firstNumber 0
get secondNumber 0
get result 0
getPhaseId called

Now type in two numbers into the input boxes and click the Add button. The browser now displays the result of the addition, as shown in Figure 4.

the result of addition
Figure 4. The result of addition

More importantly, check the message that gets displayed in the console:

get firstNumber 0
get secondNumber 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
----------------------------------------
Set firstNumber 10
Set secondNumber 20
get firstNumber 10
get secondNumber 20
get result 30

Summary

In this article, you have learned the most important characteristic of JSF applications that makes them different from other servlet/JSP applications: event-driven-ness. You have also built a simple JSF application that consists of one JSP page. More importantly, you have written the action listener that responds to an action event.

Real-life JSF applications are more complex, often with multiple JSP pages. In this case, you need to be able to navigate from one JSP page to another. However, this is a topic for another article.

Budi Kurniawan is a senior J2EE architect and author.


Return to ONJava.com.