The Java EE 5 Tutorial

Request Processing

When a user clicks on a button or a hyperlink, the application navigates to a new page or reloads the current page. Navigation to all pages listed in Table 37–2 is configured in the web/WEB-INF/faces-config.xml file using a set of navigation rules.

As described in Configuring Navigation Rules, the JavaServer Faces navigation mechanism matches a logical outcome String or an action method to one of the navigation rules to determine which page to open next. The button or hyperlink that the user clicks specifies the logical outcome String or action method with its action attribute.

Although it’s not necessary to do so, the web client of Duke’s Bank uses an Java SE Enum class to encapsulate all the possible logical outcomes for the application:

public enum Navigation  {
    main,
     accountHist,
     accountList,
     atm,
     atmAck,
     transferFunds,
     transferAck,
     error,
     logout;

    public Object action() {
        return this;
    }
}

If you are not familiar with enums, see http://java.sun.com/javase/6/docs/technotes/guides/language/enums.html.

A managed bean is needed to expose the enum to the expression language so that a page can access its logical outcomes. In this case, the Navigation enum class is accessed through the NavigationEnumBean:

public class NavigationEnumBean extends EnumManagedBean {
    public NavigationEnumBean() {
        super(Util.Navigation.class);
    }
}

NavigationEnumBean extends a special bean class that includes a method to return an enum constant, which represents a logical outcome:

public Enum getEnum(String enumName) {
    return Enum.valueOf(e, enumName);
}

The application also includes a custom EL resolver, EnumResolver, which resolves expressions that reference an instance of this bean class. You create a resolver if you want expressions to particular kinds of objects resolved in a special way that is not already supported by the EL mechanism. See Resolving Expressions for more information on EL resolvers.

The resolver calls the bean’s getEnum method from its getValue method to return the enum constant:

public Object getValue(ELContext elContext, Object base, Object property) {
    if ((base != null && property != null)
        && base instanceof EnumManagedBean) {
            elContext.setPropertyResolved(true);
            return
                 ((EnumManagedBean)base)
                    .getEnum(property.toString());
    }
    return null;
}

A tag’s action attribute references a particular constant of the enum to specify a logical outcome. The following commandLink tag appears on the links.jsp page:

<h:commandLink value="#{bundle.Logoff}"
    action="#{navigation.logout.action}"/>

The action attribute has the expression #{navigation.logout.action} to invoke the action method of the Navigation enum. This returns the enum constant, representing the logical outcome, logout.

The following piece of a navigation rule configuration in the faces-config.xml file corresponds to the action attribute expression of the preceding commandLink tag. It causes the logoff.jsp page to open if the logout logical outcome is returned.

<navigation-rule>
    ...
    <navigation-case>
        <description>
            Any action that returns "logout" should go to the
            logoff page and invalidate the session.
        </description>
        <from-action>logout</from-action>
        <to-view-id>/logoff.jsp</to-view-id>
</navigation-rule>

When a page in the application is rendered, it is constructed with the aid of a template mechanism. Every page includes the template.jsp page, which in turn includes certain subcomponents, such as banner.jsp, into the page depending on which page is being rendered. The screendefinitions.jspf page, included in template.jsp, determines which page to render based on the current view ID, which identifies the UI component tree that represents the page to be rendered. The screendefinitions.jspf page accesses the view ID with this expression from its definition tag:

<tt:definition name="bank"
         screen="${facesContext.viewRoot.viewId}">

Based on the view ID, the templating mechanism will include specific components into the page.