Skip Headers

Oracle® Application Development Framework Developer's Guide 10g Release 3 (10.1.3) B25386-01 |
| Home | Solution Area | Contents | Index

Previous | Next |

# 9.4 Creating Navigation Using Dynamic Outcome Values

Instead of explicitly specifying a static outcome value in a navigation component, you can dynamically determine the outcome by binding the `action` attribute of a navigation component to an action method. An action method is a method in a backing bean (also known as a managed bean) that can perform an action (such as saving user input) and return an outcome value. The outcome value determines the next page that should be displayed after the method performs an action. For example, an action method that verifies user input on a page might return one outcome if the input is valid and return another outcome if the input is invalid. Each of these different outcomes could trigger different navigation cases, causing the application to navigate to one of two possible target pages. As with static outcomes, a dynamic outcome triggers a navigation case that contains a matching `from-outcome` value or a default navigation case.

The method bound to a navigation component must be a public method with no parameters, and it must return a `String` representing the outcome of the action. An action method can return one of multiple outcomes depending on the processing it carries out. In other words, you can define conditional outcomes in the method logic. The outcome returned by the method must be defined in one of the cases in the page's navigation rules (unless you are using default rules, which handle all outcomes not specified in any navigation case).

Tip: In ADF applications, most processing of data objects is handled by methods on the data control. Therefore, if a navigation component that uses dynamic outcomes needs to perform some processing on a data object (for example, creating, editing, deleting), it should be bound to a backing bean method that injects the ADF binding container. When a backing bean injects the ADF binding container, it calls the specified data control method to handle the processing of the data and then, based on the results, returns a navigation outcome to the UI component. For more information about injecting the binding container into a backing bean, see Section 10.5, "Overriding Declarative Methods".

## 9.4.1 How to Create Navigation Components Using Dynamic Outcomes

If you want the outcome of a navigation component to be determined dynamically, you can bind the component to a method on a backing bean. The backing bean can execute some application logic and, depending on the results, return an outcome. The returned outcome will determine the navigation rule that is implemented. For information about creating backing beans, see Section 4.5, "Creating and Using a Backing Bean for a Web Page".

Note: If you enabled auto-binding by selecting the Automatically Expose UI Components in a New Managed Bean or the Automatically Expose UI Components in an Existing Managed Bean options when you created the page, any navigation component you create will automatically contain a binding to the managed bean (also known as a backing bean) defined for the page.

To create a navigation component that binds to a backing bean:

1. From the ADF Faces Core page of the Component Palette, drag a CommandButton or a CommandLink onto the page.

   Tip: You can also use the JSF `commandButton` and `commandLink` components.

2. In the visual editor double-click the UI component to display the Bind Action Property dialog, as shown in Figure 9-5.

   Figure 9-5 Bind Action Property Dialog

   The Bind Action Property dialog enables you to identify the backing bean and method to which you want to bind the component. If enabled auto-binding when you created the page, the Bind Action Property dialog does not display the option for specifying a static outcome.

3. In the Bind Action Property dialog, identify the backing bean and the method to which you want to bind the component using one of the following techniques:

   - Click New to create a new backing bean. The Create Managed Bean dialog is displayed. Use this dialog to name the bean and the class.

   - Select an existing backing bean and method from the dropdown lists.

4. After identifying the backing bean and method, click OK on the Bind Action Property dialog.

   JDeveloper displays the source editor. If it is a new method, the source editor displays a stub method, as shown in Example 9-13. If it is an existing method, the source editor displays that method, instead of the stub method.

   Example 9-13 Stub Method Created in the Backing Bean

       public String commandButton1_action() {
           // Add event code here...
           return null;
       }

5. Add any required processing logic to the method.

6. Change the return values of the method to the appropriate outcome strings.

   You may want to write conditional logic to return one of multiple outcomes depending on certain criteria. For example, you might want to return `null` if there is an error in the processing, or another outcome value if the processing was successful. A return value of `null` causes the navigation handler to forgo evaluating navigation cases and to immediately redisplay the current page.

   Tip: To trigger a specific navigation case, the outcome value you enter in the `action` attribute must exactly match the outcome value in the navigation rule, including uppercase and lowercase letters.

## 9.4.2 What Happens When You Use Dynamic Outcome Values

When you create a navigation component that specifies a dynamic outcome, JDeveloper adds an EL expression to the `action` attribute of the component tag. The EL expression references the backing bean method that will perform some application processing, such as saving user input, and return an outcome value.

Example 9-14 shows a button on the SRCreateConfirm page of the SRDemo application that uses a dynamic outcome value. The button was created using the ADF Faces `commandButton` component, which is available from the Data Control Palette context menu. The user clicks the button to create a new service request.

Example 9-14 Navigation Component That Uses Dynamic Outcomes

    <af:commandButton text="#{res['srcreate.submit.button']}"
                            partialSubmit="false"
                            action="#{backing_SRCreateConfirm.createSRButton_action}"
                            id="createSRButton"/>

The button's `action` attribute is bound to the `createSRButton_action` method on the `SRCreateConfirm` backing bean, which is shown in Example 9-15. The backing bean method starts by validating the user input. If the user did not enter a problem description for the service request, the method returns an outcome value of `Back`. If the user did enter a problem description, the method creates the service request and returns an outcome value of `Complete`. (To create the service request, the method injects the ADF binding container, which calls the `createServiceRequest` data control method. For more information about injecting the binding container into a backing bean method, see Section 10.5, "Overriding Declarative Methods".)

Example 9-15 Backing Bean Method That Returns a Dynamic Outcome

        public String createSRButton_action() {
            BindingContainer bindings = getBindings();

            //Before we proceed check that the user has entered a description
            Object description =
                ADFUtils.getBoundAttributeValue(bindings, "SRCreatePageDef",
                                                "problemDescription");
            if (description == null) {
                FacesContext ctx = FacesContext.getCurrentInstance();
                ctx.addMessage(null,
                               JSFUtils.getMessageFromBundle("srcreate.
                                    missingDescription",FacesMessage.SEVERITY_ERROR));

                return "Back";
            } else {
                //now find the facade method binding
                OperationBinding operationBinding =
                    bindings.getOperationBinding("createServiceRequest");
                ServiceRequest result = (ServiceRequest)operationBinding.execute();

                //Put the number of the created service ID onto the request as an
                // example of passing data in that way
                Integer svrId = result.getSvrId();
                ExternalContext ectx =
                    FacesContext.getCurrentInstance().getExternalContext();
                HttpServletRequest request = (HttpServletRequest)ectx.getRequest();
                request.setAttribute("SRDEMO_CREATED_SVRID", svrId);

                //Force a requery on the next visit to the SRList page
                UserSystemState.refreshNeeded();
                return "Complete";
            }
        }

Example 9-16 shows the navigation rule that handles the two possible outcomes returned by the backing bean.

Example 9-16 Navigation Rule Referenced by a Dynamic Outcome

    <navigation-rule>
        <from-view-id>/SRCreateConfirm.jspx</from-view-id>
        <navigation-case>
          <from-outcome>Back</from-outcome>
          <to-view-id>/SRCreate.jspx</to-view-id>
        </navigation-case>
        <navigation-case>
          <from-outcome>Complete</from-outcome>
          <to-view-id>/SRCreateDone.jspx</to-view-id>
        </navigation-case>
    </navigation-rule>

## 9.4.3 What Happens at Runtime

When a user clicks a navigation component that has a dynamic outcome, the action method on the backing bean is executed. The method usually processes some user input and then returns an outcome value to the page. The JSF navigation handler evaluates the outcome returned by the action method and matches it to a navigation case that has the same value defined in the `from-outcome` element. The matching rule is then implemented and the page defined in the rule's `to-view-id` element is displayed. If the method does not return an outcome or if the outcome does not match any of the navigation cases, the user remains on the current page.

When using an action method to handle navigation in an application, you don't need to implement an `ActionListener` interface to invoke the method because JSF uses a default `ActionListener` to invoke action methods for page navigation: the method's logical outcome value is used to tell the JSF navigation handler what page to use for the render response.

## 9.4.4 What You May Need to Know About Using Default Cases

If an action method returns different outcomes depending on the processing logic, you may want to define a default navigation case to prevent having the method return an outcome that is not covered by any specific navigation case.

Default navigation cases catch all the outcomes not specifically covered in other navigation cases. To define a default navigation case, you can exclude the `from-outcome` element, which tells the navigation handler that the case should apply to any outcome not handled by another case.

For example, suppose you are using an action method to handle a Submit command button. You can handle the success case by displaying a particular page for that outcome. For all other outcomes, you can display a page explaining that the user cannot continue. Example 9-17 shows the navigation cases for this scenario.

Example 9-17 Navigation Rule with a Default Navigation Case

    <navigation-rule>
      <from-view-id>/order.jsp</from-view-id>
      <navigation-case>
        <from-action>#{backing_home.submit}</from-action>
        <from-outcome>success</from-outcome>
        <to-view-id>/summary.jsp</to-view-id>
      </navigation-case>
      <navigation-case>
        <from-action>#{backing_home.submit}</from-action>
        <to-view-id>/again.jsp</to-view-id>
      </navigation-case>
    </navigation-rule>

In the example, the first navigation case is a dynamic navigation case, where an action method is determining the outcome. If the outcome is `success`, the user navigates to the `/summary.jsp` page.

The second navigation case is a default navigation case that catches all other outcomes returned by the action method and displays the `/action.jsp` for all outcomes. Notice that the default case does not specify a `from-outcome``` value, which causes this case to be implemented if the outcome returned by the action method does not match any of the other cases.

## 9.4.5 What You May Need to Know About Action Listener Methods

You can use action listener methods in a navigation component when you have an action that needs information about the user interface. Suppose you have a button that uses an image of the state of California, and you want a user to be able to select a county and display information about that county. You could implement an action listener method that determines which county is selected by storing an outcome for each county, and an action method that uses the outcome value to navigate to the correct county page.

To use an action method and action listener method on a component, you would reference them as shown in Example 9-18.

Example 9-18 Navigation Component with Action Listener and Action Methods

    <h:commandButton image="californiastate.jpg"
                     actionListener="#{someBean.someListenmethod}"
                     action="#{someBean.someActionmethod}"/>