Download
FAQ
History
HomeHomeNext API
Search
Feedback
Divider

Navigating Between Pages

As explained in section Navigation Model, this release of JavaServer Faces technology includes a new navigation model that eliminates the need to define navigation rules programmatically with an ApplicationHandler.

Now you define page navigation rules in a centralized XML file called the application configuration resource file. See Application Configuration for more information on this file.

Any additional processing associated with navigation that you might have included in an ApplicationHandler you now include in an Action class. An Action object is referenced by the UICommand component that triggers navigation. The Action object returns a logical outcome based on the results of its processing. This outcome describes what happened during the processing. The Action that was invoked and the outcome that is returned are two criteria a navigation rule uses for choosing which page to navigate to.

This rest of this section explains:

What is Navigation?

Navigation is a set of rules for choosing a page to be displayed. The selection of the next page is determined by:

A single navigation rule defines how to navigate from one particular page to any number of other pages in an application. The JavaServer Faces implementation chooses the proper navigation rule according to what page is currently displayed.

Once the proper navigation rule is selected, the choice of which page to access next from the current page depends on the Action that was invoked and the outcome that was returned.

The UICommand component either specifies an outcome from its action property or refers to an Action object with its actionRef property. The Action object performs some processing and returns a particular outcome string.

The outcome can be anything the developer chooses, but Table 21-17 on page 886 lists some outcomes commonly used in Web applications.

Table 21-17 Common outcome strings
Outcome
What it means
"success"
Everything worked. Go on to the next page
"error"
Something is wrong. Go on to an error page
"logon"
The user needs to log on first. Go on to the logon page.
"no results"
The search did not find anything. Go to the search page again.

Usually, the Action class performs some processing on the form data of the current page. For example, the Action class might check if the username and password entered in the form match the username and password on file. If they match, the Action returns the outcome "success". Otherwise, it returns the outcome "failure". As this example demonstrates, both the Action and the outcome are necessary to determine the proper page to access.

Here is a navigation rule that could be used with the example Action class processing described in the previous paragraph:

<navigation-rule>
  <from-tree-id>logon.jsp</from-tree-id>
  <navigation-case>
    <from-action-ref>LogonForm.logon</from-action-ref>
    <from-outcome>success</from-outcome>
    <to-tree-id>/storefront.jsp</to-tree-id>
  </navigation-case>
  <navigation-case>
    <from-action-ref>LogonForm.logon</from-action-ref>
    <from-outcome>failure</from-outcome>
    <to-tree-id>/logon.jsp</to-tree-id>
    </navigation-case>
</navigation-rule> 

This navigation rule defines the possible ways to navigate from logon.jsp. Each navigation-case element defines one possible navigation path from logon.jsp. The first navigation-case says that if LogonForm.logon returns an outcome of "success", storefront.jsp will be accessed. The second navigation-case says that logon.jsp will be re-rendered if LogonForm.logon returns "failure".

For a complete description of how to define navigation rules, see Configuring Navigation Rules in faces-config.xml.

The next section describes what happens behind the scenes when navigation occurs.

How Navigation Works

As section The Lifecycle of a JavaServer Faces Page explains, a JavaServer Faces page is represented by a component tree, which is comprised of all of the components on a page. To load another page, the JavaServer Faces implementation accesses a component tree identifier and stores the tree in the FacesContext. The new navigation model determines how this tree is selected.

Any UICommand components in the tree are automatically registered with the default ActionListenerImpl. When one of the components is activated--such as by a button click--an ActionEvent is emitted. If the Invoke Application phase is reached, the default ActionListenerImpl handles this event.

The ActionListenerImpl retrieves an outcome--such as "success" or "failure"--from the component generating the event. The UICommand component either literally specifies an outcome with its action property or refers to a JavaBeans component property of type Action with its actionRef property. The invoke method of the Action object performs some processing and returns a particular outcome string.

After receiving the outcome string, the ActionListenerImpl passes it to the default NavigationHandler. Based on the outcome, the currently displayed page, and the Action object that was invoked, the NavigationHandler selects the appropriate component tree by consulting the application configuration file (faces-config.xml).

The next section explains how to define navigation rules for your application in the faces-config.xml file.

Configuring Navigation Rules in faces-config.xml

An application's navigation configuration consists of a set of navigation rules. Each rule is defined by the navigation-rule element in the faces-config.xml file. See Setting Up The Application Configuration File for information on how to set up the faces-config.xml file for use in your application.

Here are two example navigation rules:

<navigation-rule>
  <from-tree-id>/more.jsp</from-tree-id>
  <navigation-case>
    <from-outcome>success</from-outcome>
    <to-tree-id>/buy.jsp</to-tree-id>
  </navigation-case>
  <navigation-case>
    <from-outcome>out of stock</from-outcome>
    <from-action-ref>
      CarOptionServer.carBuyAction
    </from-action-ref>
    <to-tree-id>/outofstock.jsp</to-tree-id>
  </navigation-case>
</navigation-rule>
<navigation-rule>
  <navigation-case>
    <from-outcome>error</from-outcome>
    <to-tree-id>/error.jsp</to-tree-id>
  </navigation-case>
</navigation-case> 

The first navigation rule in this example says that the application will navigate from more.jsp to:

The second navigation rule says that the application will navigate from any page to error.jsp if the application encountered an error.

Each navigation-rule element corresponds to one component tree identifier, defined by the optional from-tree-id element. This means that each rule defines all the possible ways to navigate from one particular page in the application. If there is no from-tree-id element, the navigation rules defined in the navigation-rule element apply to all the pages in the application. The from-tree-id element also allows wildcard matching patterns. For example, this from-tree-id element says the navigation rule applies to all the pages in the cars directory:

<from-tree-id>/cars/*</from-tree-id> 

As shown in the example navigation rule, a navigation-rule element can contain zero or more navigation-case elements. The navigation-case element defines a set of matching criteria. When these criteria are satisfied, the application will navigate to the page defined by the to-tree-id element contained in the same navigation-case element.

The navigation criteria are defined by optional from-outcome and from-action-ref elements.

The from-outcome element defines a logical outcome, such as "success". The from-action-ref element refers to a bean property that returns an Action object. The Action object's invoke method performs some logic to determine the outcome and returns the outcome.

The navigation-case elements are checked against the outcome and the Action parameters in this order:

Once any of these cases are matched, the component tree defined by the to-tree-id element will be selected for rendering.

The section Referencing An Action From a Component explains how to write the tag corresponding to the UICommand component to return an outcome.

Referencing An Action From a Component

The command_button and command_hyperlink tags have two attributes used to specify an outcome, which is matched against the from-outcome elements in the application configuration file in order to select the next page to be rendered. These attributes are:

This command_button tag could be used with the example navigation rule from the previous section:

<h:command_button id="buy2" key="buy" bundle="carDemoBundle"
    commandName="buy" actionRef="CarServer.carBuyAction"> 

The actionRef attribute refers to CarOptionServer.carBuyAction, a bean property that returns an Action object, whose invoke method returns the logical outcome.

If the outcome matches an outcome defined by a from-outcome element in application configuration file the component tree specified in that navigation case is selected for rendering if one of these is true:

Suppose that the buy2 command_button tag used the action attribute instead of the actionRef attribute:

<h:command_button id="buy2" key="buy" bundle="carDemoBundle"
    commandName="buy" action="out-of-stock"> 

If this outcome matches an outcome defined by a from-outcome element in the application configuration file, the component tree corresponding to this navigation case is selected for rendering, regardless of whether or not the same navigation case also contains a from-action-ref element.

The next section explains how to write the bean and the Action class.

Using an Action Object With a Navigation Rule

It's common for applications to have a choice of pages to navigate to from a given page. You usually need to provide some application-specific processing that determines which page to access in a certain situation. The processing code goes into the invoke method of an Action object. Here is the Action bean property and the Action implementation used with the examples in the previous two sections:

import javax.faces.application.Action;
...
public class CurrentOptionServer extends Object{ 
...
  public Action getCarBuyAction() {
    if (carBuyAction == null) {
      carBuyAction = new CarBuyAction();
    return carBuyAction;
  } 
  class CarBuyAction extends Action {
    public String invoke() {
      if (carId == 1 && currentPackageName.equals("Custom") &&
        currentPackage.getSunRoofSelected()) {
          currentPackage.setSunRoofSelected(false);
        return "out of stock";
      } else {
        return "success"
      }
  }
} 

The CarBuyAction.invoke method checks if the first car is chosen, the Custom package is chosen and the sunroof option is selected. If this is true, the sunroof checkbox component value is set to false, and the method returns the outcome, "out of stock". Otherwise, the outcome, "success" is returned.

As shown in the example in section Configuring Navigation Rules in faces-config.xml, when the NavigationHandler receives the "out-of-stock" outcome, it selects the /outofstock.jsp component tree.

As shown in the example code in this section, it's a good idea to include your Action class inside the same bean class that defines the property returning an instance of the Action. This is because the Action class will often need to access the bean's data to determine what outcome to return. Section Combining Component Data and Action Objects discusses this concept in more detail.

Divider
Download
FAQ
History
HomeHomeNext API
Search
Feedback
Divider

All of the material in The Java(TM) Web Services Tutorial is copyright-protected and may not be published in other works without express written permission from Sun Microsystems.