22 Creating Complex Task Flows

This chapter describes how to use advanced features of ADF task flows in an ADF application.

This chapter includes the following sections:

22.1 About Creating Complex Task Flows

After creating a task flow, adding activities to it, and configuring control flow between the activities, you can extend the task flow´s functionality by adding some of the features described in the following list:

  • Bounded task flows can be configured to include additional transactional management facilities beyond those provided by the underlying data controls so that a Fusion web application can commit or roll back the data controls associated with the task flow's activities as a group.

  • Reentry options can be configured for bounded task flows to determine the response if a user clicks the browser's back button.

  • Task flows contain a number of features that allow you to proactively handle exceptions. In addition, you can write custom code to handle exceptions thrown by a task flow

  • Task flows can also be configured to capture the state of a Fusion web application at a particular instance using save points. These allow you to save the application's state if, for example, a user leaves a page without finalizing a task.

  • Train components are ADF Faces components that render navigation items to guide a user through a multistep process. You can configure a bounded task flow to render these navigation items by default for the view activities in a task flow.

  • Task flow templates can serve as a starting point for the creation of task flows that share common elements.

  • Create a page hierarchy from the view activities that the default unbounded task flow in your application (and additional task flows in the application) reference.

  • Invoke initializers and finalizers when a bounded task flow is entered and exited. An initializer is custom code that is invoked when a bounded task flow is entered. A finalizer is custom code that is invoked when a bounded task flow is exited via a task flow return activity or because an exception occurred. The finalizer is a method on a managed bean. Common finalizer tasks include releasing all resources acquired by the bounded task flow and performing cleanup before exiting the task flow.

    You specify both the initializer and the finalizer as an EL expression for a method on a managed bean, for example:

    #{pageFlowScope.modelBean.releaseResources}

    There are two techniques for running initializer code at the beginning of the bounded task flow, depending on whether or not the task flow may be reentered via a browser back button:

22.1.1 Complex Task Flows Use Cases and Examples

Figure 22-1 shows the Structure window for the customer registration task flow in the Fusion Order Demo application. This task flow implements many of the use cases discussed in Section 22.1, "About Creating Complex Task Flows." For example, it specifies an error page to handle errors, makes use of the ADF Faces train component to render navigation items, and specifies two task flow return activities that either commit or roll back changes that the task flow makes as part of transaction management. For more information about the Fusion Order Demo application that contains this task flow, see Chapter 2, "Introduction to the ADF Sample Application."

Figure 22-1 Customer Registration Task Flow in the Structure Window

Customer Registration Task Flow in the Structure Window

22.1.2 Additional Functionality for Complex Task Flows

You may find it helpful to understand other ADF features before you configure or use task flows. Additionally, you may want to read about what you can do with your task flows. Following are links to other functionality that may be of interest.

22.2 Sharing Data Controls Between Task Flows

You can share data controls between task flows. A called bounded task flow can reference and modify the value of the data control owned by its calling task flow. This allows the called task flow to share the same data control instance as its parent. Both task flows look in the same place, the data control frame, to get the data control instance.

A data control frame is the mechanism that associates one or more task flows and their data controls. Task flows making use of the task flow transaction management options when committing or rolling back use the data control frame to know which data controls to perform the transaction operations on. A data control frame is created at runtime for your application's unbounded task flow and any bounded task flow with a data-control-scope value of isolated. When a task flows specifies a data-control-scope value of shared, the called task flow uses the data control frame of the calling task flow rather than create its own. This allows the called task flow to share data control instances attached to the data control frame. Alternatively, if a called task flow specifies a data-control-scope value of isolated, a new data control frame is created and a new instance of any data controls used by the bounded task flow will be attached to the newly-created data control frame.

To specify whether data controls are shared between the calling and called task flows, you must set a data-control-scope value of either shared or isolated on the called bounded task flow. The default value is shared.

If data-control-scope is set to shared on both the calling and called bounded task flow, the data control frame used will be the one for the calling task flow. In Example 22-1, the data control frame for Bounded Task Flow A will also be used by both B and C.If data-control-scope is set to isolated on both the calling and called bounded task flow, each task flow uses its own data control frame.

Example 22-1 Sharing Data Controls

Bounded Task Flow A - isolated
  Bounded Task Flow B - shared
    Bounded Task Flow C - shared

Note:

A task flow that is configured to share data controls cannot share data controls with the calling task flow if the calling task flow uses a URL to invoke the called task flow. ADF Controller throws an exception if this scenario occurs.

A called bounded task flow can share its caller's data controls to any depth. For example, Task Flow A can share data controls with called bounded Task Flow B. Called Task Flow C can share the same data controls.

A bounded task flow that specifies data-control-scope as shared and is used within an ADF region shares the data controls of the task flow in the parent view port. For more information about view ports, see Section 21.1.2, "About View Ports and ADF Regions."

A new data control frame is created for the unbounded task flow in the call stack of each RootViewPort. Each browser window is isolated from all other browser windows within the same HTTP session. The browser windows do not share data controls. However, if an end user opens a modal dialog in a secondary browser window, the primary and secondary browser windows have the same server-side state and share data controls. For more information about using modal dialogs, see Section 23.2, "Running a Bounded Task Flow in a Modal Dialog."

Data controls are not instantiated until needed. One of two things can occur when a parent task flow calls a child task flow that specifies data-control-scope as shared (the default) and references a data control named D:

  1. If a data control named D already exists in the parent task flow's data control frame, then the child task flow's reference to D resolves to the existing data control named D that is in scope.

  2. If a data control named D does not exist in the parent task flow's data control frame, then Oracle ADF instantiates the first data control named D that it finds when performing a top-down search through the DataBindings.cpx files for the task flow call stack.

In the example above, assume that the parent task flow comes from an ADF Library JAR and that it defines a data control usage D in its DataBindings.cpx file in the ADF Library JAR. Also, the child task flow defines a data control usage named D in its DataBindings.cpx file.

If, when the parent task flow calls the child task flow, the data control D from the parent task flow's ADF Library JAR is already instantiated, then the child task flow uses it. If it is not already instantiated, then the data control D from the parent task flow will be instantiated and used by the child task flow. In particular, in this task flow calling scenario, the child task flow's data control D will not be instantiated.

For more information about data controls, see Section 13.3, "Exposing Application Modules with Oracle ADF Data Controls."

22.2.1 How to Share a Data Control Between Task Flows

You share data controls between task flows by specifying a value for the data-control-scope element of the called task flow.

Before you begin:

It may be helpful to have an understanding of the properties that determine how you share data controls between task flows. For more information, see Section 22.2, "Sharing Data Controls Between Task Flows."

You may also find it helpful to understand functionality that can be added using other task flow features. For more information, see Section 22.1.2, "Additional Functionality for Complex Task Flows."

To share a data control between task flows:

  1. In the Application Navigator, double-click the called task flow.

  2. In the Property Inspector, expand the Behavior section and select the Share data controls with calling task flow checkbox.

    Note:

    After you select the Share data controls with calling task flow checkbox, you may need to configure transaction options for the task flow. For more information, see, Section 22.3.3, "What You May Need to Know About Sharing Data Controls and Managing Transactions".

22.2.2 What Happens When You Share a Data Control Between Task Flows

JDeveloper writes an entry in the source file for the called task flow when you select the Share data controls with calling task flow checkbox, as illustrated in Example 22-2.

At runtime, the called task flow shares data controls with the calling task flow.

Example 22-2 Metadata to Share Data Controls Between Task Flows

<task-flow-definition id="task-flow-definition">
    ...
    <data-control-scope id="__1">
      <shared/>
    </data-control-scope>
    ...
  </task-flow-definition>

22.3 Managing Transactions in Task Flows

A transaction is a persisted collection of work that can be committed or rolled back together as a group. You can use a bounded task flow to represent a transaction and to declaratively manage transaction boundaries. In the Fusion Order Demo application, the customer registration and employee registration task flows are both implemented with the use of task flow return activities. The Cancel button implements rollback in the task flows. The Register button on the reviewCustomerInfo.jsff and reviewEmployeeInfo.jsff page fragment files implement commit functionality.

An end user can navigate from the shopping cart to initiate a backorder request for an out-of-stock item. The backorder request application is implemented as a bounded task flow that initiates a new transaction upon entry.

Transaction options on the called bounded task flow specify whether a called bounded task flow should join an existing transaction, create a new one, or create a new one only if there is no existing transaction.

If the called bounded task flow is able to start a new transaction (based on the transaction option that you selected), you can specify whether the transaction will be committed or rolled back when the task flow returns to its caller. The commit and rollback options are set on the task flow return activity that returns control back to the calling task flow. The same task flow that starts a transaction must also resolve the transaction.

In a called bounded task flow, you can specify two different return task flow activities that result in either committing or rolling back a transaction in the called bounded task flow. Each of the task flow return activities passes control back to the same calling task flow. The difference is that one task flow return activity specifies the commit option, while the other specifies the rollback option. As shown in Figure 22-2, if transaction processing successfully completes, control flow passes to the success task flow return activity, which specifies options to commit the transaction. If the transaction is cancelled before completion, the cancel task flow activity specifies options to roll back the transaction.

Figure 22-2 Task Flow Return Activities in Called Bounded Task Flow

Multiple task flow return activities.

If no transaction option is specified, a transaction is not started on entry of the called bounded task flow. A runtime exception is thrown if the bounded task flow attempts to access transactional services.

Use the restore-save-point option on the task flow return activity if you want to discard the changes an end user makes within a called bounded task flow when the called bounded task flow exits. ADF Controller rolls back to the previous ADF Model save point that was created when the bounded task flow was entered. The restore-save-point option applies only to cases when a bounded task flow is entered by joining an existing transaction (either the requires-existing-transaction or requires-transaction option is also specified) and a save point is created upon entry.

If you use the task flow transaction management features that commit and rollback the data controls associated with the data control frame of the current task flow, you must use task flow return activities with their End Transaction property set to commit or rollback, or programatically commit the associated data control frame. Alternatively if you use the <No Controller Transaction> setting or you only want to commit or rollback one data control, use the associated commit or rollback operations from the Data Control panel or programatically execute the associated commit and rollback bindings.

22.3.1 How to Enable Transactions in a Bounded Task Flow

Define transaction options on a bounded task flow that is called by another task flow. Add a task flow return activity on the called bounded task flow that returns control to the task flow that calls the bounded task flow.

Before you begin:

It may be helpful to have an understanding of what a transaction is and how you can configure it. For more information, see Section 22.3, "Managing Transactions in Task Flows."

You may also find it helpful to read about additional functionality that you can add using other task flow features. For more information, see Section 22.1.2, "Additional Functionality for Complex Task Flows."

To enable a bounded task flow to run as a transaction:

  1. In the Application Navigator, double-click the source file for the called bounded task flow.

  2. In the overview editor, click the Behavior navigation tab and expand the Transaction section.

  3. Choose one of the following from the dropdown list:

    • <No Controller Transaction>: The called bounded task flow does not use the task flow transaction management facilities to commit or rollback all data controls attached to the task flow and associated data control frame. Instead, you must individually commit and rollback data controls attached to the task flow.

    • Always Use Existing Transaction: When called, the bounded task flow participates in an existing transaction already in progress.

    • Use Existing Transaction If Possible: When called, the bounded task flow either participates in an existing transaction if one exists, or starts a new transaction upon entry of the bounded task flow if one doesn't exist.

    • Always Begin New Transaction: A new transaction starts when the bounded task flow is entered, regardless of whether or not a transaction is in progress. The new transaction completes when the bounded task flow exits.

    Note:

    After choosing a transaction option, you may also need to select the Share data controls with calling task flow option for the bounded task flow to determine whether there are any interactions between the options. For more information, see Section 22.3.3, "What You May Need to Know About Sharing Data Controls and Managing Transactions."

  4. Optionally, deselect the Share data controls with calling task flow checkbox so that data controls are not shared with the calling task flow if you chose one of the following options in step 3:

    • Use Existing Transaction If Possible

    • Always Begin New Transaction

    The default behavior is to share data controls. For more information, see Section 22.3.3, "What You May Need to Know About Sharing Data Controls and Managing Transactions."

  5. Optionally, select the No save point on task flow entry checkbox to prevent the creation of an ADF Model save point on task flow entry if you chose one of the following options in step 3:

    • Always Use Existing Transaction

    • Use Existing Transaction If Possible

    An ADF Model save point is a saved snapshot of the ADF Model state. Selecting the No save point on task flow entry checkbox means that overhead associated with a save point is not created for the transaction.

  6. Select the task flow return activity in the called bounded task flow.

  7. In the Property Inspector, expand the Behavior section.

  8. If the called bounded task flow supports creation of a new transaction (bounded task flow specifies Use Existing Transaction If Possible or Always Begin New Transaction options), select one of the following in the End Transaction dropdown list:

    • commit: Select to commit the existing transaction to the database.

    • rollback: Select to roll back a new transaction to its initial state on task flow entry. This has the same effect as cancelling the transaction.

  9. In the Restore Save Point dropdown list, select true if you want changes the user makes within the called bounded task flow to be discarded when the task flow exits. The save point that was created upon task flow entry will be restored.

22.3.2 What Happens When You Specify Transaction Options

Example 22-3 shows the metadata for transaction options on a called bounded task flow. The <new-transaction> element indicates that a new transaction always starts when the called bounded task flow is invoked.

Example 22-3 Called Bounded Task Flow Metadata

 <task-flow-definition id="trans-taskflow-definition">     
    <default-activity>taskFlowReturn1</default-activity>
    <transaction>
      <new-transaction/>
    </transaction>
    <task-flow-return id="taskFlowReturn1">
      <outcome>
        <name>success</name>
        <commit/>
      </outcome>
    </task-flow-return>
  </task-flow-definition>

Example 22-3 also shows the metadata for transaction options on the task flow return activity on the called task flow. The <commit/> element commits the existing transaction to the database. The <outcome> element specifies a literal outcome, for example, success, that is returned to the caller when the bounded task flow exits. The calling ADF task flow can define control flow rules based on this outcome to For more information about defining control flow upon return, see Section 19.7, "Using Task Flow Return Activities."

22.3.3 What You May Need to Know About Sharing Data Controls and Managing Transactions

Data controls cannot be shared across more than one transaction at the same time. If your task flow is involved in managing transactions, the value you select for the data-control-scope option may affect the transaction option settings for a bounded task flow. Table 22-1 describes how these options interact.

The ADF Model layer exposes the DataControlFrame interface to manage a transaction in which the data controls within the frame participate. The DataControlFrame interface exposes methods such as:

  • beginTransaction()

  • commit()

  • rollback()

Similarly, ADF Controller allows a task flow to demarcate a transaction boundary, to begin a transaction at task flow entry, and to either commit or roll back the transaction on task flow exit. It does this by invoking methods exposed by ADF Model layer's DataControlFrame interface.

ADF Controller supports the transaction options listed in Table 22-1. The behavior of these transaction options depends on whether you select or deselect the Share data controls with calling task flow checkbox (XML element: <data-control-scope>) in the overview editor for a task flow.

Table 22-1 Transaction Settings Behavior

Transaction Setting Share Data Control Scope Isolate Data Control Scope

<No Controller Transaction>

The DataControlFrame is shared without the need for an open transaction on the frame.

A new DataControlFrame is created without an open transaction.

Always Begin New Transaction

XML element: <new-transaction/>

Begins a new transaction if one is not already open and throws an exception if one is already open.

Always begins a new transaction.

Always Use Existing Transaction

XML element: <requires-existing-transaction/>

Throws an exception if the transaction is not already open.

Invalid. The checkbox cannot be deselected.

Use Existing Transaction if Possible

XML element: <requires-transaction/>

Begins a new transaction if one is not already open.

Always begins a new transaction.


22.4 Reentering Bounded Task Flows

To deal with cases in which the end user clicks the back button to navigate back into a bounded task flow that was already exited, you can specify task-flow-reentry options for the bounded task flow. These options specify whether a page in the bounded task flow can be reentered.

Upon reentry, bounded task flow input parameters are evaluated using the current state of the application, not the application state existing at the time of the original bounded task flow entry.

Note:

Different browsers handle the back button differently. In order to ensure that back button navigation is properly detected across all browsers, the view activities within the task flow need to be properly configured. When a task flows uses the reentry-not-allowed or reentry-outcome-dependent option, the redirect attribute on each view activity within the task flow should be set to true. See Section 19.3, "Using URL View Activities" for more information on how to configure view activities.

22.4.1 How to Set Reentry Behavior

You can set reentry behavior on a bounded task flow by specifying task-flow-reentry options.

Before you begin:

It may be helpful to have an understanding of what reentry options you can configure for a bounded task flow. For more information, see Section 22.4, "Reentering Bounded Task Flows."

You may also find it helpful to read about additional functionality that you can add using other task flow features. For more information, see Section 22.1.2, "Additional Functionality for Complex Task Flows."

To set reentry behavior:

  1. In the Application Navigator, double-click the source file for the bounded task flow.

  2. In the overview editor, click the Behavior navigation tab.

  3. In the Task Flow Reentry dropdown list, choose one of the following:

    • reentry-allowed: Reentry is allowed on any view activity within the bounded task flow.

    • reentry-not-allowed: Reentry of the bounded task flow is not allowed. If you specify reentry-not-allowed on a bounded task flow, an end user can still click the browser back button and return to a page within the bounded task flow. However, if the user does anything on the page such as clicking a button, an exception (for example, InvalidTaskFlowReentry) is thrown indicating the bounded task flow was reentered improperly. The actual reentry condition is identified upon the submit of the reentered page.

      You can set up an exception handler to display the exception and route control flow in order to navigate to the default activity of the called bounded task flow. If the bounded task flow was not called from another bounded task flow, a normal web error is posted and handled as specified in the web.xml file.

    • reentry-outcome-dependent: Reentry of a bounded task flow using the browser back button is dependent on the outcome that was received when the same bounded task flow was previously exited via task flow return activities. If specified, any task flow return activities on the called bounded task flow must also specify either reentry-allowed or reentry-not-allowed to define outcome-dependent reentry behavior.

      If you choose this option, the user can navigate to a task flow using a back button based solely on how the user originally exited the task flow. For example, a task flow representing a shopping cart can be reentered if the user exited by canceling an order, but not if the user exited by completing the order.

22.4.2 How to Set Outcome-Dependent Options

You can set outcome-dependent options on bounded task flows that have specified the reentry-outcome-dependent option, as described in Section 22.4.1, "How to Set Reentry Behavior."

Before you begin:

It may be helpful to have an understanding of what reentry options you can configure for a bounded task flow. For more information, see Section 22.4, "Reentering Bounded Task Flows."

You may also find it helpful to read about additional functionality that you can add using other task flow features. For more information, see Section 22.1.2, "Additional Functionality for Complex Task Flows."

To set outcome-dependent options:

  1. In the task flow diagram for the bounded task flow, select the task flow return activity.

    For information about adding a task flow return activity, see Section 19.7, "Using Task Flow Return Activities."

  2. In the Property Inspector, expand the General section.

  3. In the Name field, enter the name of literal outcome, for example, success or failure.

  4. Expand the Behavior section.

  5. In the Reentry dropdown list, choose one of the following options:

    • reentry-allowed: Reentry is allowed on any view activity within the bounded task flow.

    • reentry-not-allowed: Reentry of the bounded task flow is not allowed. If you specify reentry-not-allowed on a bounded task flow, an end user can still click the browser back button and return to a page within the bounded task flow. However, if the user does anything on the page such as clicking a button, an exception (for example, InvalidTaskFlowReentry) is thrown indicating the bounded task flow was reentered improperly. The actual reentry condition is identified upon the submit of the reentered page.

      You can set up an exception handler to display the exception and route control flow in order to navigate to the default activity of the called bounded task flow. If the bounded task flow was not called from another bounded task flow, a normal web error is posted and handled as specified in the web.xml file.

22.4.3 What You Should Know About Managed Bean Values Upon Task Flow Reentry

When an end user reenters a bounded task flow using a browser's back button, and reentry is allowed, the value of a managed bean is reset to the value of the managed bean before the end user exited the bounded task flow. The managed bean value is reset before a view activity in the reentered bounded task flow renders. Any changes that occur before the reentry of the bounded task flow are lost. To change this behavior, specify the <redirect> element on the view activity in the reentered bounded task flow. When the end user reenters the bounded task flow using the back button, the managed bean has the new value from the parent task flow, not the original value from the child task flow that is reentered.

22.5 Handling Exceptions in Task Flows

During execution of a task flow, exceptions can occur that may require some kind of exception handling, for example:

  • A method call activity throws an exception.

  • A custom method you have written as a task flow intializer or finalizer throws an exception.

  • A user is not authorized to execute the activity.

To handle exceptions thrown from an activity or caused by some other type of ADF Controller error, you can designate one activity in a bounded or unbounded task flow as an exception handler.

When a task flow throws an exception, control flow passes to the designated exception handling activity. For example, the exception handling activity might be a view activity that displays an error message. Alternatively, the activity might be a router activity that passes control flow to a method based on an EL expression that evaluates the type of exception. For example:

#{controllerContext.currentViewPort.exceptionData.class.name == 'oracle.adf.controller.ControllerException'}

After control flow passes to the exception handling activity, flow from the exception handling activity uses standard control flow rules. For example, you designate a router activity as the exception handling activity. At runtime, the task flow passes control to the exception handling activity (in this example, a router activity) in response to an exception. In addition to designating the router activity as an exception handler, you can define task flow control cases that the router invokes based on the type of exception that it has to handle. This allows you to manage your end user's application session gracefully when an exception occurs. For more information, see Section 18.1.3, "About Control Flows."

You can optionally specify an exception handler for both bounded and unbounded task flows. Each task flow can have only a single exception handler. However, a task flow called from another task flow can have a different exception handler from that of the caller. In addition, a region on a page can have a different exception handler from that of the task flow containing the page. The exception handler activity can be any supported activity type, for example, a view or router activity.

If a bounded task flow does not have a designated exception handler activity, control passes to an exception handler activity in a calling bounded task flow, if there is a calling task flow and if it contains an exception handler activity. The exception is propagated up the task flow stack until either an exception handler activity or the top-level unbounded task flow is reached. If no exception handler is found, the exception is propagated to the web container.

If a bounded task flow does have a designated exception handler activity, make sure the exception handler activity leaves the application in a valid state after it handles an exception. One way to do this is to redirect to a view activity in the same task flow after the exception handler activity.

Other modules, such as the ADF Model, also provide exception handling capabilities. In certain scenarios this can determine the way that your application handles exceptions. For example, a databound method activity is a method activity that has a page definition and an EL expression with the following format:

#{bindings.somebindingname.execute}

where somebindingname is a method binding defined in the page definition.

An exception thrown by any type of binding is caught by the ADF Model which calls the reportException() method and stores the exception in the binding container. Later, when the page renders, the error displays in the page.

When a method activity invokes a method binding, there is no page to display an error that the exception raises because the exception occurs during navigation between two pages. To make the application aware of an error, Oracle ADF rethrows the exception so that it is caught by the ADF Controller exception handler mechanism that navigates to an exception handler activity if one exists.

Keep this in mind, particularly if you decide to override methods, such as the reportException() method, described in Section 16.3, "Customizing Error Handling," because in that scenario both the ADF Controller and ADF Model exception handlers will be called.

22.5.1 How to Designate an Activity as an Exception Handler

You can designate an exception handler activity for a bounded task flow running as an ADF Region. If an exception occurs in the bounded task flow and it is not handled by the task flow's exception handler, the exception is not propagated up the task flow stack of the parent page. Instead, it becomes an unhandled exception.

Before you begin:

It may be helpful to have an understanding of what exception handling options you can configure for a task flow. For more information, see Section 22.5, "Handling Exceptions in Task Flows."

You may also find it helpful to read about additional functionality that you can add using other task flow features. For more information, see Section 22.1.2, "Additional Functionality for Complex Task Flows."

To designate an activity as an exception handler for a task flow:

  1. Right-click the activity in the task flow diagram, and choose Mark Activity > Exception Handler.

    A red exclamation point is superimposed on the activity in the task flow to indicate that it is an exception handler. Figure 22-3 shows an example.

    Figure 22-3 Example of an Activity Designated as an Exception Handler

    An activity designated as an exception handler.
  2. To unmark the activity, right-click the activity in the task flow diagram, and choose Unmark Activity > Exception Handler.

    If you mark an activity as an exception handler in a task flow that already has a designated exception handler, the old handler is unmarked.

22.5.2 What Happens When You Designate an Activity as an Exception Handler

After you designate an activity to be the exception handling activity for a task flow, JDeveloper updates the task flow metadata with an <exception-handler> element that specifies the ID of the activity, as shown in Example 22-4.

Example 22-4 <exception-handler> element

<exception-handler id="__8>activityID</exception-handler>

22.5.3 How to Designate Custom Code as an Exception Handler

Rather than designate a task flow activity as the activity to invoke, you can write custom code to invoke when a task flow throws an exception. This requires you to:

  • Write a Java class that extends the class ExceptionHandler from the following package:

    oracle.adf.view.rich.context.ExceptionHandler

  • Register the Java class that you write as a service in the .adf\META-INF directory of your Fusion web application

Example 22-5 shows custom code that checks if an exception thrown by a task flow corruptions to a particular type of error message (ADF_FACES-30108). If it is, the custom code redirects the task flow to the faces/SessionExpired.jspx page.

Example 22-5 Custom Code for an Exception Handler

package oracle.fodemo.frmwkext;

import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseId;
import oracle.adf.view.rich.context.ExceptionHandler;
 
public class CustomExceptionHandler extends ExceptionHandler {
 
    public CustomExceptionHandler() {
        super();
    }
 
    public void handleException(FacesContext facesContext, Throwable throwable,
                                PhaseId phaseId) throws Throwable {
        
        String error_message;
        error_message = throwable.getMessage();
        
        if (error_message != null &&
            error_message.indexOf("ADF_FACES-30108") > -1) {
            ExternalContext ectx = facesContext.getExternalContext();
            ectx.redirect("faces/SessionExpired.jspx");
        }
 
        else {
            //Code to execute if the if condition is not met
            throw Throwable
        }
    }
}

For information about the APIs that you can use to write custom code, see the following reference documents:

Before you begin:

It may be helpful to have an understanding of what exception handling options you can configure for a task flow. For more information, see Section 22.5, "Handling Exceptions in Task Flows."

You may also find it helpful to read about additional functionality that you can add using other task flow features. For more information, see Section 22.1.2, "Additional Functionality for Complex Task Flows."

To designate custom code as an exception handler:

  1. In the .adf\META-INF directory of your application, create a directory named services so that you have the following directory path:

    application_root\.adf\META-INF\services

    where application_root refers to the root directory of application.

  2. Create a text file named oracle.adf.view.rich.context.ExceptionHandler in the services folder.

  3. Write the package name and class name of the custom code that you wrote to handle exceptions in the text file named oracle.adf.view.rich.context.ExceptionHandler.

    For example, if you want to register the custom code in Example 22-5, write the following:

    oracle.fodemo.frmwkext.CustomExceptionHandler

  4. Save and close the text file.

22.5.4 What Happens When You Designate Custom Code as an Exception Handler

At runtime, the task flow passes control to the custom code that you specified if the task flow throws an exception.

22.5.5 What You May Need to Know About Handling Exceptions During Transactions

Designate an exception handling activity for a bounded task flow that is enabled to run as a transaction. A Fusion web application attempts to commit a transaction if you set commit as the value for a task flow return activity's End Transaction property on a bounded task flow that runs as a transaction. If an exception occurs when the Fusion web application attempts to commit a transaction, the exception handling activity receives control and provides the end user with an opportunity to correct the exception. You can use the exception handling activity (for example, a view activity) to display a warning message to an end user with information about how to correct the exception and how to recommit the transaction. For information about enabling a bounded task flow as a transaction and setting commit as a value for the End Transaction property, see Section 22.3.1, "How to Enable Transactions in a Bounded Task Flow."

22.5.6 What You May Need to Know About Handling Validation Errors

For validation errors on a JSF page, you can rely on standard JSF to attach validator error messages to specific components on a page or to the whole page. A component-level validator typically attaches an error message inline with the specific UI component. There is no need to pass control to an exception handler activity.

In addition, your application should define validation logic on data controls that are executed during the Validate Model Updates phase of the JSF lifecycle. In this way, data errors are found as they are submitted to the server without waiting until attempting the final commit.

Validations done during the Validate Model Updates phase typically do not have direct access to the UI components because the intention is to validate the model after the model has been updated. These validations are often things like checking to see whether dependent fields are in sync. In these cases, the error message is usually attached to the whole page, which this logic can access.

You should attach errors detected during the Validate Model Updates phase to the JSF page, and call FacesContext.renderResponse(). This signals that following this phase, the current (submitting) page should be rendered showing the attached error messages. There is no need to pass control to an exception handler activity.

For more information, see Chapter 8, "Implementing Validation and Business Rules Programmatically".

22.6 Configuring Your Application to Use Save Points

Before you can add save points to a task flow, as described in Section 22.7, "Using Save Points in Task Flows" and configure related functionality, you need to make sure that the Fusion web application allows save points. To do this, you define a value for the <savepoint-datasource> element in the adf-config.xml file to specify the JNDI name for the data source that contains the save points' database table. You may also need to run a SQL script (adfc_create_save_point_table.sql), as described in Section 22.6.3, "What You May Need to Know About the Database Table for Save Points," to create the database table that stores save points. Once your Fusion web application starts using save points, you can use another SQL script (adfc_cleanup_save_point_table.sql) to delete expired save points.

22.6.1 How to Configure Your Fusion Web Application to Use Save Points

You define a value for the <savepoint-datasource> element in your application's adf-config.xml file to specify the JNDI name for the data source that contains the save points' database table. Optionally, you can also specify an expiration time for save points.

Before you begin:

It may be helpful to have an understanding of what save point options you can configure for a task flow. For more information, see Section 22.6, "Configuring Your Application to Use Save Points."

You may also find it helpful to read about additional functionality that you can add using other task flow features. For more information, see Section 22.1.2, "Additional Functionality for Complex Task Flows."

To configure your Fusion web application to allow save points:

  1. With the Fusion web application open in JDeveloper, open the Application Resources pane in the Application Navigator.

  2. Expand Descriptors, then expand ADF META-INF.

  3. Right-click adf-config.xml and choose Open from the context menu.

  4. On the Controller page of the overview editor, write a value for the Data Source property to specify the JNDI name for the data source that contains the save points' database table.

    For example, write the following:

    java:comp/env/jdbc/Connection1DS

    where Connection1 is the JDeveloper connection name.

  5. Optionally, write a value in seconds for the Expiration property to specify the time between when a task flow creates a save point and when the save point manager removes it. The default value is 86400 seconds.

    For more information, see Section 22.7.9, "What You May Need to Know About the Time-to-Live Period for a Save Point."

  6. Save the adf-config.xml file.

22.6.2 What Happens When You Configure a Fusion Web Application to Use Save Points

JDeveloper generates an entry, similar to that illustrated in Example 22-6, in the adf-config.xml file to specify the JNDI name for the data source that contains the save points' database table.

Example 22-6 Save Point Data Source Definition in adf-config.xml

<adf-controller-config xmlns="http://xmlns.oracle.com/adf/controller/config">
    ...
    <savepoint-datasource>
      java:comp/env/jdbc/Connection1DS
    </savepoint-datasource>
    <savepoint-expiration>
      86399
    </savepoint-expiration>
  </adf-controller-config>

For more information about the adf-config.xml file, see Section A.11, "adf-config.xml".

22.6.3 What You May Need to Know About the Database Table for Save Points

A database table named ORADFCSAVPT stores save points. If this database table does not exist, it is created the first time that a save point is created if your Fusion web application has the necessary permissions to create a database table. If your Fusion web application does not have the necessary permissions, you or an administrator with the necessary permissions can use SQL scripts to create and maintain the ORADFCSAVPT database table. These SQL scripts are:

  • adfc_cleanup_save_point_table.sql

    Each save point in the ORADFCSAVPT database table has an expiration date. Use this script to delete save points that have passed their expiration date.

  • adfc_create_save_point_table.sql

    Use this script to create the ORADFCSAVPT database table that stores save points.

You can find these SQL scripts in the following directory of your JDeveloper installation:

jdev_install\oracle_common\common\sql

22.7 Using Save Points in Task Flows

You can configure a task flow to capture the state of a Fusion web application at a particular instance creating what is called a save point. This allows you to save application state if, for example, a user leaves a page without finalizing it. The application state can be restored at a later point.

Table 22-2 describes what information a save point captures.

Table 22-2 Saved Application State Information

Saved State Information Description

User Interface State

UI state of the current page, including selected tabs, selected checkboxes, selected table rows, and table column sort order.

This state assumes the end user cannot select the browser back button on save point restore.

Managed Beans

State information saved in several possible memory scopes, including session and page flow scope. The managed beans must be serializable in order to be saved. If you have page flow scope beans that are not serializable and you attempt to create a save point, a runtime exception occurs.

Request scope is not supported since its lifespan is a single HTTP request and its lifespan can't be used to store cross request application state.

Save points will not save and restore application-scoped managed beans since they're not passivated in failover scenarios. Therefore, the application is always responsible for ensuring that all required application-scoped state is available.

Potential naming conflicts for managed beans already existing within the session scope at restore time will not occur because multiple managed beans using the same name should not be implemented within an application.

Navigation State

Task flow call stack, which ADF Controller maintains as one task flow calls another at runtime.

The task flow call stack tracks where the end user is in the application and the navigation path for getting there. The task flow stack also identifies the starting point of any persisted data transactions originated for the end user.

ADF Model State

Fusion web applications use ADF Model to represent the persisted data model and business logic service providers. The ADF Model holds any data model updates made from when the current bounded task flow begins. The model layer determines any limits on the saved state lifetime. For more information, see Chapter 43, "Application State Management".


You add a method call activity to a bounded task flow that invokes a createSavePoint method to create save points. Later, you use a save point restore activity to restore application state and data associated with the created save points.

The same save point can be used if a user repeatedly performs a save for later on a task flow instance that executes in one session within the same browser window. The new save point overwrites the existing save point when a user performs a save for later following navigation from page to page in a task flow. For more information about restoring a save point, see Section 22.7.3, "How to Restore a Save Point".

You can specify the createSavePoint method exposed by the currentViewPort node of the ADF Controller Objects in the Expression Builder. Alternatively, you can write a custom method that updates the save point with the values of attributes you specify in your custom method, as illustrated in Example 22-7.

Example 22-7 Example Custom Method for Creating a Save Point

package viewController;
 
import java.io.Serializable;
 
import oracle.adf.controller.ControllerContext;
import oracle.adf.controller.savepoint.SavePointManager;
 
public class SaveForLater implements Serializable {
    public SaveForLater() {
        super();
    }
 
    public String saveTaskFlow() {
        ControllerContext cc = ControllerContext.getInstance();
        if (cc != null) {
            SavePointManager mgr = cc.getSavePointManager();
            if (mgr != null) {
                String id = mgr.createSavePoint();
                System.out.println("Save point is being set " + id);
            ...

The SavePointListener interface exposes methods that notify clients when save point events occur. The following package contains the SavePointListener interface:

oracle.adf.controller.savepoint

Note:

All save points created inside a bounded task flow are deleted when the bounded task flow exits.

22.7.1 How to Add a Save Point to a Task Flow

You drag and drop a method call activity to the task flow and configure it to invoke the createSavePoint method or to invoke a custom method if you created one.

Before you begin:

It may be helpful to have an understanding of what save point options you can configure for a task flow. For more information, see Section 22.7, "Using Save Points in Task Flows."

You may also find it helpful to read about additional functionality that you can add using other task flow features. For more information, see Section 22.1.2, "Additional Functionality for Complex Task Flows."

Using a save point in a Fusion web application requires that you leave the value of the jbo.locking.mode property set to the default value optimistic. The value pessimistic causes an old session to lock until the session has timed out. In pessimistic mode, if you run an application and change data without committing changes to the database, you may get an error when you create a save point and try to restore it at a later point. For information about the jbo.locking.mode property, see Section 43.11.1, "How to Confirm That Applications Use Optimistic Locking."

To add a save point to a task flow:

  1. Open the bounded task flow that you want to configure and navigate to the diagram editor.

  2. In the ADF Task Flow page of the Component Palette, from the Component panel, drag and drop a Method Call activity onto the diagram.

  3. In the Property Inspector, expand the General node and write an EL expression for the Method property to specify the save point method that the method call activity invokes.

    If you use the Expression Builder to specify the createSavePoint method exposed by the currentViewPort node of the ADF Controller Objects, the resulting EL expression is similar to the following:

    #{controllerContext.currentViewPort.createSavePoint}

  4. Use a control flow to connect the method call activity with other activities in the bounded task flow.

    For more information, see Section 18.4.1, "How to Add a Control Flow Rule to a Task Flow."

  5. Optionally, configure save point options in the Fusion web application's adf-config.xml file to determine, for example, if implicit save points can be created for the application.

    For more information, see Section 22.7.7, "How to Enable Implicit Save Points."

22.7.2 What Happens When You Add Save Points to a Task Flow

JDeveloper generates entries similar to those shown in Example 22-8 in the task flow's source file when you configure a method call activity to invoke the createSavePoint method.

Example 22-8 Method Call Metadata to Invoke the createSavePoint Method

<method-call id="methodCall1">
      <method id="__3">#{controllerContext.currentViewPort.createSavePoint}</method>
    </method-call>

22.7.3 How to Restore a Save Point

Use the save point restore activity to restore a previously persisted save point for an application. The save point restore activity uses the save point that was originally created by invoking the createSavePoint method to identify the save point to restore.

You can obtain a list of the current persisted save points with createSavePoint. However, ADF Controller does not determine which save points to restore. A user must select the save point from a list or the application developer must select it programmatically. The savepoint ID is then passed to a save point restore activity to perform the restore.

Before you begin:

It may be helpful to have an understanding of what save point options you can configure for a task flow. For more information, see Section 22.7, "Using Save Points in Task Flows."

You may also find it helpful to read about additional functionality that you can add using other task flow features. For more information, see Section 22.1.2, "Additional Functionality for Complex Task Flows."

To add a save point restore activity to a bounded or unbounded task flow:

  1. Open the bounded or unbounded task flow where you want to add the save point restore activity and navigate to the diagram editor.

  2. In the ADF Task Flow page of the Component Palette, from the Components panel, drag a Save Point Restore activity and drop it on the diagram for the task flow.

  3. In the Property Inspector, expand the General node and write an EL expression for the Save Point ID property that, when evaluated, retrieves the save point that was originally created when the createSavePoint method was invoked.

    If you use the Expression Builder to specify the getSavePoint method of the ADF Controller Objects, the resulting EL expression is similar to the following:

    #{SessionScope.myBean.savepointID}

22.7.4 What Happens When You Restore a Save Point

JDeveloper generates entries similar to Example 22-9 in the task flow's source file when you add a save point restore activity that gets a save point ID.

Example 22-9 Metadata for a Save Point Restore Activity in a Task Flow

<save-point-restore id="savePointRestore1">
      <save-point-id id="__4">#{sessionScope.myBean.savepointID}</save-point-id>
    </save-point-restore>

22.7.5 How to Use the Save Point Restore Finalizer

When using the save point restore activity, you may need to invoke application-specific logic as part of restoring the application state. You can write an EL expression for the Save Point Restore Finalizer property of a bounded task flow that specifies a finalizer method. The bounded task flow invokes the specified method after the task flow's state has been restored. It performs any necessary logic to make sure that the application's state is correct before proceeding with the restore.

Before you begin:

It may be helpful to have an understanding of what save point options you can configure for a task flow. For more information, see Section 22.7, "Using Save Points in Task Flows."

You may also find it helpful to read about additional functionality that you can add using other task flow features. For more information, see Section 22.1.2, "Additional Functionality for Complex Task Flows."

To use the save point restore finalizer:

  1. In the Structure window, right-click the node for the bounded task flow (task-flow-definition) and select Go to Properties.

  2. In the Property Inspector, expand the General tab, and select Expression Builder from the Save Point Restore Finalizer dropdown menu.

  3. Write an EL expression that specifies the finalizer method to invoke.

22.7.6 What Happens When a Task Flow Invokes a Save Point Restore Finalizer

JDeveloper generates entries similar to Example 22-10 in the task flow's source file when you write an EL expression for the Save Point Restore Finalizer property.

Example 22-10 Metadata to Invoke a Save Point Restore Finalizer

<task-flow-definition id="task-flow-definition1">
    <save-point-restore-finalizer id="__2">#{sessionScope.MyBean.invokeFinalizer}
      </save-point-restore-finalizer>
  </task-flow-definition>

22.7.7 How to Enable Implicit Save Points

A save point in a task flow can be categorized as implicit or explicit. An explicit save point requires an end user action before a bounded or unbounded task flow creates a save point. For example, an end user clicks a button that invokes a method call activity that, in turn, creates a save point.

An implicit save point can only originate from a bounded task flow. It includes everything from when the originating task flow creates a save point. It occurs when data is saved automatically because:

  • A session times out due to end user inactivity

  • An end user logs out without saving the data

  • An end user closes the only browser window, thus logging out of the application

  • An end user navigates away from the current application using control flow rules (for example, uses a goLink component to go to an external URL) and having unsaved data.

Enabling implicit save points requires you to add an element to your Fusion web application's adf-config.xml file and to make the bounded task flow critical.

You configure the adf-config.xml file in your application and the bounded task flow(s) for which you want to create implicit save points. Enabling implicit save points involves a performance cost because your Fusion web application has to do extra work that it would otherwise not do. This is why you have to explicitly enable implicit save points in your application and specify the task flows to which it applies.

Before you begin:

It may be helpful to have an understanding of what save point options you can configure for a task flow. For more information, see Section 22.7, "Using Save Points in Task Flows."

You may also find it helpful to read about additional functionality that you can add using other task flow features. For more information, see Section 22.1.2, "Additional Functionality for Complex Task Flows."

To enable implicit save points:

  1. In the Application Resources panel of the Application Navigator, expand Descriptors, then expand ADF META-INF.

  2. Right-click adf-config.xml and choose Open from the context menu.

  3. On the Controller page of the overview editor, select the Enable Implicit Savepoints checkbox.

    JDeveloper generates the following entry in the adf-config.xml file:

    <adf-controller-config xmlns="http://xmlns.oracle.com/adf/controller/config">
        ...
        <enable-implicit-savepoints>true</enable-implicit-savepoints>
    </adf-controller-config>
    

    For more information about the adf-config.xml file, see Section A.9, "adfc-config.xml."

  4. In the Application Navigator, double-click the source file for the bounded task flow.

  5. In the overview editor, click the Behavior navigation tab and select the Critical checkbox.

22.7.8 What You May Need to Know About Enabling Implicit Save Points

If multiple windows are open when the implicit save point is created, a different save point is created for each browser window. This includes everything from the root view port of the browser window on down. You can write an EL expression for the Method property of a method call activity to retrieve the list of implicit save points using the savePointManager node under ADF Controller Objects. The resulting EL expression is similar to the following:

ControllerContext.savePointManager.listSavePointIds

Implicit save points are generated only if a critical task flow is present in any of the page flow stacks for any view port under the current root view port. An implicit save point is not generated if the request is for an ADF Controller resource, such as:

  • Task flow call activity

  • Task flow return activity

  • Save point restore activity

  • A dialog

Implicit save points are deleted when the task flow at the bottom of the stack completes or a new implicit save point is generated, whichever comes earlier.

22.7.9 What You May Need to Know About the Time-to-Live Period for a Save Point

An application-level property (savepoint-expiration) that is defined in the adf-config.xml file determines the period between when a task flow creates a save point and when the save point manager removes it (time-to-live period). The default value is 86400 seconds (24 hours).

You can change the time-to-live period for individual save points by calling the setSavePointTimeToLive method on an instance of SavePointManger from the following package:

oracle.adf.controller.savepoint

An instance of SavePointManager can be obtained as follows:

SavePointManager mgr = ControllerContext.getInstance().getSavePointManager();

Example 22-11 shows the syntax for the setSavePointTimeToLive method.

Example 22-11 Syntax for the setSavePointTimeToLive Method

    public void setSavePointTimeToLive(long timeInSeconds) {
       }

If you supply a value for the setSavePointTimeToLive method argument (timeInSeconds in Example 22-11) equal to or less than zero, the default value is used (86400).

The SavePointManger defines methods that help you manage save points. For example, it defines getSavePoint and removeSavePoint methods that can retrieve and remove save points. Note that the removeSavePoint method does not get called automatically when a save point expires. You must explicitly call the removeSavePoint method to remove save points (including expired save points) from the ORADFCSAVPT database table. Alternatively, Oracle ADF provides a SQL script (adfc_cleanup_save_point_table.sql) that removes expired save points. For more information, see Section 22.6.3, "What You May Need to Know About the Database Table for Save Points."

Consider calling the setSavePointTimeToLive method at the same time that you call the method to create save points, as illustrated in Example 22-7. For more information about the SavePointManger, see the Oracle Fusion Middleware Java API Reference for Oracle ADF Controller.

22.8 Using Train Components in Bounded Task Flows

You can create a task flow as a train. This allows you to create a user interface where you navigate end users through a multistep process. For example, the Fusion Order Demo application's customer registration task flow renders a train that navigates end users through a number of train stops in order to complete the customer registration process, as illustrated in Figure 22-4.

ADF Faces provides the user interface components that render the train functionality in the task flow view activities that appears to the end user. These components are the train and trainButtonBar components. Figure 22-4 shows the defineAddresses.jsff page (a task flow view activity) using the train and trainButtonBar components to navigate the end user through the address creation step in the customer registration task flow.

Figure 22-4 Train and Train Button Bar Components in the Customer Registration Task Flow

Train Component in the FOD Customer Registration Task Flow

The train component in Figure 22-4 renders four train stops. Each stop corresponds to a page fragment in the customer registration task flow where the end user can enter and review information to complete the registration process. Figure 22-4 shows the Address train stop where the end user enters an address for postage. The other stops are:

  • Basic Information

  • Payment Options

  • Review

The Train Button Bar component, also shown in Figure 22-4, is optional and provides additional controls to navigate between the train stops. This component can be used in conjunction with the train component to provide multiple ways to navigate through train stops.

Bounded task flows and task flow templates can make use of these train components if you select the Create Train checkbox on the dialogs provided by JDeveloper to create a bounded task flow or a task flow template. A bounded task flow or a task flow template can render one train only. If you want to use multiple trains, create a separate bounded task flow or task flow template for each train.

Figure 22-5 displays an extract from the design time view of the customer registration task flow where you can see the basicInformation and defineAddresses view activities that render at runtime as the Basic Information and Address train stops in Figure 22-4.

The dotted line labeled goNext connecting the basicInformation view activity to the defineAddresses view activity indicates the sequence in which the end user navigates between the view activities when the view activities render as train stops.

Figure 22-5 Detail of Customer Registration Task Flow

Detail of customer-registration-task-flow

JDeveloper displays a context menu with options to change the position of the activity when your right-click a view activity or task flow call activity that is configured as a train stop, as illustrated in Figure 22-6.

Figure 22-6 Context Menu to Edit a Train Stop

Context Menu to Edit a Train Stop

Configure a task flow call activity as a train stop when you want to group a number of activities as a train stop or call a child train stop. For example, there are cases when other task flow activities, such as router and method call activities, should be considered part of a train stop along with the corresponding view activity. A method call activity might need to precede a view activity for initialization purposes. When grouped this way, the activities can be performed as a set each time the train stop is visited. For more information, see Section 22.8.3, "Grouping Task Flow Activities to Execute Between Train Stops."

Branching using router activities and control flow cases is supported on the task flow diagram containing the train, as well as in child bounded task flows called from the train.

22.8.1 Creating a Task Flow as a Train

You need to configure a bounded task flow to use train components before you can implement the type of functionality discussed in Section 22.8, "Using Train Components in Bounded Task Flows." Use one of the methods outlined in the following list to configure a bounded task flow to use train components:

  • Select the Create Train checkbox in the dialog that JDeveloper displays when you create a new bounded task flow or task flow template.

    For more information, see Section 18.2, "Creating a Task Flow" or Section 22.9, "Creating Task Flow Templates."

  • Right-click an existing bounded task flow in the diagram and choose Train > Create Train from the context menu that JDeveloper displays.

  • Open an existing bounded task flow in the overview editor, click the Behavior navigation tab and select the Train checkbox.

Once you have configured the bounded task flow to use train components, you drag and drop the task flow activities that you want to render in the train to the diagram in the bounded task flow.

22.8.1.1 How to Create a Train in a Bounded Task Flow

You drag and drop the task flow activities that you want to render in the train to the diagram for the bounded task flow.

Before you begin:

Make sure that you configure the bounded task flow to use train components, as described in Section 22.8, "Using Train Components in Bounded Task Flows."

It may be helpful to have an understanding of the configuration options that you can configure for a train. For more information, see Section 22.8.1, "Creating a Task Flow as a Train."

You may also find it helpful to read about additional functionality that you can add using other task flow features. For more information, see Section 22.1.2, "Additional Functionality for Complex Task Flows."

To create a train in a bounded task flow:

  1. Open the bounded task flow or task flow template where you want to render train stops.

  2. Drag each view activity or JSF page you want to include in the train to the diagram for the bounded task flow.

    • If you drag a JSF page, JDeveloper automatically adds a view activity to the diagram.

    • Double-click any view activity that you drag to the diagram to invoke the dialog to create a new JSF page.

    You can reorder the train stop sequence at a later point. For more information, see Section 22.8.4, "Disabling the Sequential Behavior of Train Stops in a Train."

  3. In the diagram for the bounded task flow, double-click each view activity that you want to define as a train stop.

    JDeveloper displays a dialog to create a new JSF page if the view activity is not yet associated with a JSF page. Use the dialog to create a new JSF page.

    If the view activity is already associated with a JSF page, JDeveloper opens the page.

  4. In the ADF Faces page of the Component Palette, from the General Controls panel, in the Location group, drag a Train, and, optionally, a Train Button Bar component and drop it on the JSF page.

    You must manually add each Train and Train Button Bar component that you want to appear in a task flow view activity. Consider using a page template. For more information, see Section 24.2, "Using Page Templates."

22.8.1.2 What Happens When You Create a Task Flow as a Train

JDeveloper writes the <train/> element to the source file for the bounded task flow or task flow template that you enable as a train, using one of the methods outlined in Section 22.8.1, "Creating a Task Flow as a Train."

JDeveloper writes entries to the JSF page where you added train and trainButtonBar components. Example 22-12 shows code snippets from the defineAddresses.jsff page fragment in the Fusion Order Demo application. Both types of train component bind to instances of the train model object (trainModel).

Example 22-12 Metadata for Train Components in the Fusion Order Demo Application

 <af:train value="#{controllerContext.currentViewPort.taskFlowContext.trainModel}"
         id="t1"/>
  ...
  <af:trainButtonBar value="#{controllerContext.currentViewPort.taskFlowContext.trainModel}"
        id="tbb1"/>

Dotted lines appear between each view activity that you add to the bounded task flow and define as a train stop, as illustrated in Figure 22-5. The dotted lines indicate the order in which the bounded task flow navigates through the train stops. JDeveloper defines the sequence in the order that you add the view activities to the bounded task flow. You can change the sequence. For more information, see Section 22.8.4, "Disabling the Sequential Behavior of Train Stops in a Train." You can also skip a train stop. For more information, see Section 22.8.6, "Configuring a Train to Skip a Train Stop."

22.8.2 Invoking a Child Bounded Task Flow from a Train Stop

An alternative approach to grouping task flow activities in one train stop, as described in Section 22.8.3, "Grouping Task Flow Activities to Execute Between Train Stops," is to create another bounded task flow as a train that you invoke from your current bounded task flow. We refer to this bounded task flow as a child bounded task flow. You configure the parent bounded task flow to invoke it using a task flow call activity. To implement this functionality, you:

  • Create a child bounded task flow as a train

  • Add the task flow activities that you want end users to access from the train stop on the parent bounded task flow to the child bounded task flow

  • Designate a task flow call activity as a train stop in the parent bounded task flow to invoke the child bounded task flow

  • Add a task flow return activity to the child bounded task flow that returns control to the parent bounded task flow once the child bounded task flow finishes execution

Task flow activities in the child bounded task flow execute together regardless of whether the end user visits the train stop for the first time or returns at a later point. Nonview task flow activities in the child bounded task flow typically precede the view activity in the child bounded task flow's flow control. You can invoke a child bounded task flow from a bounded task flow that itself is a child to another bounded task flow.

22.8.2.1 How to Invoke a Child Bounded Task Flow From a Train Stop

You create a bounded task flow as a train, add task flow activities to it, and configure a task flow call activity on the parent bounded task flow to invoke it.

Before you begin:

It may be helpful to have an understanding of the configuration options that you can configure for a child bounded task flow that you invoke from a train. For more information, see Section 22.8.2, "Invoking a Child Bounded Task Flow from a Train Stop."

You may also find it helpful to read about the additional functionality that you can add using other task flow features. For more information, see Section 22.1.2, "Additional Functionality for Complex Task Flows."

To invoke a child bounded task flow from a train stop:

  1. Create a child bounded task flow as a train. For more information, see Section 22.8.1, "Creating a Task Flow as a Train."

  2. Add the task flow activities that you want the child bounded task flow to invoke to the child bounded task flow. In particular, make sure that you add a task flow return activity to the child bounded task flow to return control to the parent task flow when the child bounded task flow finishes execution.

    For more information, see Section 19.7, "Using Task Flow Return Activities."

  3. Add a task flow call activity to the parent task flow to render as a train stop that invokes the child bounded task at runtime.

    For more information, see Section 19.6, "Using Task Flow Call Activities."

22.8.3 Grouping Task Flow Activities to Execute Between Train Stops

You can group task flow activities together to form a single train stop. For example, the train stop in the Fusion Order Demo application that renders as Address at runtime groups together the following task flow activities:

  • defineAddress view activity

  • createAddress method call activity

  • addressDetails view activity

Each time a user visits the runtime Address train stop, the customer registration task flow provides access to the task flow activities listed previously. The defineAddresses view activity renders the train stop and the associated defineAddresses.jsff page fragment. The defineAddresses.jsff page fragment, in turn, exposes a command button to invoke the createAddress method call activity. This method call activity validates user input in the Address page and defines an outcome that (optionally) passes control to the addressDetails view activity. The addressDetails view activity renders the Address Information page at runtime where an end user may choose to enter additional addresses.

Figure 22-7 Task Flow Activities Grouped into One Train Stop

Task Flow Activities Grouped into One Train Stop

The train considers all task flow activities that lead from the first nonview activity through the next view activity to be part of the train. Make sure that all task flow activities, except for view and task flow call activities, for the train stop follow the view or task flow call activity that you define as a train stop.

You can also group task flow activities to execute between train stops. Figure 22-8 shows a possible configuration where a method call activity (doSomethingBeforePage2) invokes before control flow passes to page2. The callMethodBeforePage2 wildcard control flow rule passes control to the doSomethingBeforePage2 method call activity. This method call activity defines a fixed outcome (continue) that passes control to the next train stop (page2) in the train.

Figure 22-8 Method Call Activity Between Train Stops

Method Call Activity Between Train Stops

22.8.4 Disabling the Sequential Behavior of Train Stops in a Train

By default, train stops are sequential. This means end users can select a train stop only after visiting the previous train stop in the train. Figure 22-9 shows the train component that the customer registration task flow renders. End users cannot visit the Payment options and Review train stops until they first visit the Address train stop. All train stops in this train are sequential.

Figure 22-9 Sequential Train Stops in the Customer Registration Task Flow

Sequential Train Stops in Customer Registration Task Flow

You can change this default behavior (make a train stop nonsequential) by configuring the view activity that renders the train stop to make it nonsequential.

22.8.4.1 How to Disable the Sequential Behavior of a Train

You write a value for the task flow view activity's sequential property that evaluates to false at runtime.

Before you begin:

It may be helpful to have an understanding of the configuration options that you can configure for a train. For more information, see Section 22.8, "Using Train Components in Bounded Task Flows."

You may also find it helpful to read about additional functionality that you can add using other task flow features. For more information, see Section 22.1.2, "Additional Functionality for Complex Task Flows."

To disable the sequential behavior of a train stop:

  1. In the Application Navigator, double-click the source file for the bounded task flow containing the view activity that renders the train stop.

  2. In the diagram for the bounded task flow, select the view activity.

  3. In the Property Inspector, expand the Train Stop and write a value in the Sequential field to determine if the train stop is sequential or nonsequential.

    Write false or write an EL expression that resolves to false at runtime to make the train stop nonsequential. For example, write an EL expression similar to the following:

    #{myTrainModel.isSequential}

22.8.4.2 What Happens When You Disable the Sequential Behavior a Train Stop

JDeveloper writes an entry to the source file for the bounded task flow, as illustrated in Example 22-13.

Example 22-13 Metadata to Disable the Sequential Behavior of a Train Stop

<view id="paymentOptionDetails">
      <page>/account/paymentOptionDetails.jsff</page>
      <train-stop id="__1">
        <sequential>#{myTrainModel.isSequential}</sequential>
      </train-stop>
    </view>

Figure 22-10 shows the corresponding runtime view when the value specified for sequential evaluates to false. End users can now navigate directly to payment options by clicking the Payment options train stop.

Figure 22-10 Train with a Nonsequential Train Stop

Train with a Nonsequential Train Stop

22.8.5 Changing the Label of a Train Stop

You can configure a train stop to display a label that you define. The label that you define can be a static value or a value in a resource bundle that you reference using an EL expression, for example. For more information about using localized strings, see the "Internationalizing and Localizing Pages" chapter of the Oracle Fusion Middleware Web User Interface Developer's Guide for Oracle Application Development Framework.

22.8.5.1 How to Change the Label of a Train Stop

You change the label of a train stop by configuring a value for the view activity's Display Name property.

Before you begin:

It may be helpful to have an understanding of the configuration options that you can configure for a train. For more information, see Section 22.8, "Using Train Components in Bounded Task Flows."

You may also find it helpful to read about additional functionality that you can add using other task flow features. For more information, see Section 22.1.2, "Additional Functionality for Complex Task Flows."

To change the label of a train stop:

  1. In the Application Navigator, double-click the source file for the bounded task flow containing the view activity that renders the train stop.

  2. In the diagram for the bounded task flow, select the view activity.

  3. In the Property Inspector, expand the Description section and write a value in the Display Name to specify the label that the train stop renders at runtime.

    Write a literal value or write an EL expression that references a value in a resource bundle to render at runtime.

22.8.5.2 What Happens When You Change the Label of a Train Stop

JDeveloper writes an entry to the source file for the bounded task flow, as illustrated in Example 22-14.

Example 22-14 Metadata to Change the Label of a Train Stop

<view id="basicInformation">
      <display-name>Basic Information</display-name>
      <page>/account/basicInformation.jsff</page>
      <train-stop>
        <display-name>Basic Information</display-name>
      </train-stop>
    </view>

At runtime, the Fusion web application displays the value you specified for the display-name property as the label for the train stop.

22.8.6 Configuring a Train to Skip a Train Stop

You can configure a train so that it skips an individual train stop. At runtime, the Fusion web application disables the train stop that you configure to skip. The end user can only navigate to next train stop in the train.

Implement this functionality if you want the train to execute at a train stop other than the first train stop. For example, configure train stops 1 and 2 to skip if you want to execute train stop 3 first. Use this approach rather than defining the view activity associated with the train stop as the default activity, as discussed in Section 18.2.3, "What You May Need to Know About the Default Activity in a Bounded Task Flow."

22.8.6.1 How to Configure a Train to Skip a Train Stop

You write a value for the view activity's skip property that evaluates to true at runtime.

Before you begin:

It may be helpful to have an understanding of the configuration options that you can configure for a train. For more information, see Section 22.8, "Using Train Components in Bounded Task Flows."

You may also find it helpful to read about additional functionality that you can add using other task flow features. For more information, see Section 22.1.2, "Additional Functionality for Complex Task Flows."

To configure a train to skip a train stop:

  1. In the Application Navigator, double-click the source file for the bounded task flow containing the view activity that renders the train stop.

  2. In the diagram for the bounded task flow, select the view activity.

  3. In the Property Inspector, expand the Train Stop and write a value in the Skip field to determine if the train navigates to the train stop or skips it.

    Write true or write an EL expression that resolves to true at runtime to make the train skip the train stop. For example, write an EL expression similar to the following:

    #{myTrainModel.shouldSkip}

22.8.6.2 What Happens When You Configure a Train to Skip a Train Stop

JDeveloper writes an entry to the source file for the bounded task flow, as illustrated in Example 22-15.

Example 22-15 Metadata to Make a Train Skip a Train Stop

 <view id="defineAddresses">
      <display-name>Address</display-name>
      <page>/account/defineAddresses.jsff</page>
      <train-stop>
        <display-name>Address</display-name>
         <skip>#{myTrainModel.shouldSkip}</skip>
      </train-stop>
    </view>

Example 22-15 shows the corresponding runtime view when the value specified for skip evaluates to true. End users must now navigate to the next train stop in the train (Payment options) if the train is sequential.

Figure 22-11 Train Configured to Skip a Train Stop

Train Configured to Skip a Train Stop

22.9 Creating Task Flow Templates

You can create task flow templates for yourself or other application developers to use as a starting point when creating new bounded task flows. Unbounded task flows cannot be created using task flow templates. A bounded task flow created from a task flow template will have definitions for the same set of task flow activities, control flows, input parameters, and managed beans as the task flow template.

An example use case for a task flow template is where you define a task flow activity as an exception handler on a bounded task flow. The task flow activity could be a view activity associated with a page that you display to end users when an exception occurs. Rather than define this view activity in each bounded task flow, you define it in a task flow template and select the task flow template when you create new bounded task flows. For more information about exception handling, see Section 22.5, "Handling Exceptions in Task Flows."

You can base a new task flow template on an existing task flow template. You can also refactor an existing bounded task flow to create a new task flow template. For more information, see Section 18.6.3, "How to Convert Bounded Task Flows".

When you create a bounded task flow or another task flow template based on a task flow template, you can specify that subsequent changes you make to a task flow template be automatically propagated to bounded task flows and templates. To do this, you select the Update the Task Flow When the Template Changes checkbox in the dialog that you use to create a bounded task flow or a template. Subsequent changes that you make to the task flow template (add new view activities, for example) get propagated to the bounded task flows. You can change, update, or disassociate the parent task flow template of a child bounded task flow or task flow template at any point during development of the child.

At runtime, the contents of a child bounded task flow or a child task flow template combine with the contents of the parent task flow template if you selected the Update the Task Flow When the Template Changes checkbox when creating the child. The child task flow and task flow template override the parent task flow template when conflict occurs, even if you selected the Update the Task Flow When the Template Changes checkbox when creating the child task flow or task flow template. For example, you create a parent task flow template to use as a train, as described in Section 22.8, "Using Train Components in Bounded Task Flows," and then create a bounded task flow based on this task flow template. Later, you disable the train component on the parent task flow template. The child task flow overrides the parent task flow template and continues to execute as a train.

Table 22-3 describes in more detail how ADF Controller resolves conflicts between parent task flow templates and child task flows and child task flow templates.

Table 22-3 Conflict Resolution between Parent Templates and Child Task Flows

Bounded Task Flow Metadata Combination Algorithm

Default activity

Child bounded task flow or child task flow template overrides parent task flow template.

Transaction

Child bounded task flow or child task flow template overrides parent task flow template as an entire block of metadata, including all subordinate elements.

Task flow reentry

Child bounded task flow or child task flow template overrides parent task flow template as an entire block of metadata, including all subordinate elements.

Control flow rules

Combination algorithm occurs at the control flow case level, not the control flow rule level. Control flow cases fall into the following categories:

  • Both from action and from outcome specified

  • Only from action specified

  • Only from outcome specified

  • Neither from action nor from outcome specified

Each of these categories is merged additively. The child bounded task flow or template overrides parent task flow template for identical matches within each of the four categories.

Input parameter definitions

Child bounded task flow or child task flow template overrides parent task flow template for identical input parameter definition names.

Return value definitions

Child bounded task flow or child task flow template overrides parent task flow template for identical return value definition names.

Activities

Child bounded task flow or child task flow template overrides parent task flow template for identical activity IDs.

Managed beans

Child bounded task flow or child task flow template overrides parent task flow template for identical managed bean names.

Initializer

Child bounded task flow or child task flow template overrides parent task flow template.

Finalizer

Child bounded task flow or child task flow template overrides parent task flow template.

Critical

Child bounded task flow or child task flow template overrides parent task flow template.

Use page fragments

Child bounded task flow or child task flow template overrides parent task flow template.

Exception handler

Child bounded task flow or child task flow template overrides parent task flow template.

Security - permission

Child bounded task flow or child task flow template overrides parent task flow template.

Privilege maps are additive. Child bounded task flow or child task flow template overrides parent task flow template for identical privilege map operations.

Security - transport guarantee

Child bounded task flow or child task flow template overrides parent task flow template.

Train

Child bounded task flow or child task flow template overrides parent task flow template.


Validations at both design time and runtime verify that the resulting parent-child extension hierarchy does not involve cycles of the same task flow template.

22.9.1 How to Create a Task Flow Template

You create a task flow template by selecting ADF Task Flow Template from JDeveloper's New Gallery.

Before you begin:

It may be helpful to have an understanding of what task flow template options you can configure. For more information, see Section 22.9, "Creating Task Flow Templates."

You may also find it helpful to read about additional functionality that you can add using other task flow features. For more information, see Section 22.1.2, "Additional Functionality for Complex Task Flows."

To create a task flow template:

  1. In the Application Navigation, right-click the project where you want to create the task flow and choose New.

  2. In the New Gallery, expand Web Tier, select JSF/Facelets and then ADF Task Flow Template, and click OK.

  3. In the Create ADF Task Flow Template dialog, choose the appropriate options:

    • File Name: Accept the default value proposed by JDeveloper or enter a new file name. The value is used to name the XML source file for the task flow template you create. The source file includes the activities and control flow rules that are in the task flow template. The default name for the XML source file is task-flow-template.xml.

    • Create with Page Fragments: Leave this checkbox selected (the default) if you expect that a bounded task flow based on the template will be used as an ADF region. Clear the checkbox if you want to add JSF pages instead of JSF page fragments to a task flow based on the task flow template.

  4. Click OK.

22.9.2 What Happens When You Create a Task Flow Template

As shown in Example 22-16, an XML file is created each time you create a new task flow template using JDeveloper. You can find the XML file in the Application Navigator in the location that you specified in the Directory field of the Create ADF Task Flow Template dialog, for example,.../WEB-INF.

The contents of the XML source file for the task flow template can be similar to those of a bounded task flow. One difference is the inclusion of the <task-flow-template> tag.

Example 22-16 Task flow template source file

<?xml version="1.0" encoding="windows-1252" ?>
<adfc-config xmlns="http://xmlns.oracle.com/adf/controller" version="1.2" id="__1">
  <task-flow-template id="task-flow-template">
     <default-activity>view1</default-activity>
     <view id="view1">view1.jsff</view>
  </task-flow-template>
</adfc-config>

22.9.3 What You May Need to Know About Task Flow Templates

If you use a task flow template that contains bindings, you must change the component IDs of task flows based on the task flow template. Doing this makes sure that the IDs are unique. Task flows generated from the template inherit the same ID as the template. This may cause an exception at runtime. For more information, see Section 24.2.1, "How to Use ADF Data Binding in ADF Page Templates."

If your Fusion web application has configured ADF security, you have to make grants on both the task flow template and task flows that use the template. Usually, the grant on the task flow template is to the anonymous-role application role so that the grant that really matters is on the task flow, but not always. For more information about ADF security, see Section 35, "Enabling ADF Security in a Fusion Web Application."

22.10 Creating a Page Hierarchy Using Task Flows

Creating a page hierarchy is a useful way of organizing the JSF pages in your Fusion web application so that end users can more easily navigate the application. End users access information on the pages by navigating a path of links. Figure 22-12 shows a sample page hierarchy.

Figure 22-12 Page Hierarchy

Page Hierarchy

To navigate this hierarchy, an end user clicks links on each page to drill down or up to another level of the hierarchy. For example, clicking Human Resources on the Fusion App home page displays the Human Resources page hierarchy shown in Figure 22-12. Clicking the link on the Benefits tab displays the page hierarchy shown in Figure 22-13.

Figure 22-13 Benefits Page

Benefits Page

The user can click links on the Benefits page to display other pages, for example, the Medical, Dental or Vision pages. The breadcrumbs on each page indicate where the current page fits in the hierarchy. The user can click each node in a breadcrumb to navigate to other pages in the hierarchy. The bold tab labels match the path to the current page shown the breadcrumbs.

Pages referenced by view activities in a bounded task flow can also be included in any page hierarchy that you generate. Figure 22-14 shows the runtime view of a page hierarchy that renders view activities referenced by a bounded task flow.

Figure 22-14 Runtime Menu Hierarchy Including a Bounded Task Flow

Runtime Menu Hieararchy Including a Bounded Task Flow

You can use ADF Controller with an XMLMenuModel implementation to create the previously-discussed page hierarchies. If you do, JDeveloper generates the following for you:

  • Control flow metadata that determines the view or page to display when an end user selects a menu item

  • An XMLMenuModel metadata file

  • Default navigation widgets such as Previous and Next button

  • Breadcrumbs

  • Managed bean configuration

If you decide not to use ADF Controller, you can create the page hierarchy using an XMLMenuModel implementation. For more information about this method of building a page hierarchy, see the "Using a Menu Model to Create a Page Hierarchy" section in the Oracle Fusion Middleware Web User Interface Developer's Guide for Oracle Application Development Framework.

22.10.1 How to Create a Page Hierarchy

Create an unbounded task flow or open an existing one. Add view activities or bounded task flows to the unbounded task flow. Each view activity or bounded task flow that you add to the unbounded task flow contains references to pages to appear in the proposed page hierarchy. Use JDeveloper's Create ADF Menu Model dialog to generate an XMLMenuModel metadata file. Organize the item nodes in the generated XMLMenuModel metadata file to create the page hierarchy you want. Connect submenus to parent menus to finalize the hierarchy.

Figure 22-15 shows an example page hierarchy that consists of view activities:

  • The top-level menu (Home Page) is the root parent page. It contains a single tab that links to the Human Resources submenu.

    In JDeveloper, Home Page page is represented as an item node and Human Resources page as a shared node.

  • Human Resources has four tab links to Payroll, Time, Labor, and Benefits pages.

    In this menu, Human Resources is a group node that references child item nodes (Payroll, Time, and Labor) and a shared node (Benefits) that references the Benefits submenu.

  • Benefits is a group node that references child item nodes (Medical, Dental, and Vision) pages.

Figure 22-15 Menu Hierarchy

Menu hierarchy.

Note:

It is possible to create the entire menu hierarchy in one menu model. However, breaking a menu hierarchy into submenus makes maintenance easier. In addition, breaking the menu hierarchy into smaller submenu models enables each separate development organization to develop its own menu. These separate menus can later be combined using shared nodes to create the complete menu hierarchy.

Figure 22-16 shows the corresponding design-time view in JDeveloper of the unbounded and bounded task flows that render the page hierarchy shown in Figure 22-14. The unbounded task flow (adfc-config.xml) contains a view activity (view1) and a task flow call activity (task-flow-definition) that invokes the bounded task flow (task-flow-definition.xml) shown in the lower part of Figure 22-16.

Figure 22-16 Design Time Menu Hierarchy Including a Bounded Task Flow

Design Time Menu Hierarchy Including a Bounded Task Flow

22.10.1.1 How to Create an XMLMenuModel Metadata File

You use JDeveloper's Create ADF Menu Model dialog to generate an XMLMenuModel metadata file once you have defined what menus (unbounded task flows) and nodes (pages) you want to appear in the final page hierarchy.

Before you begin:

It may be helpful to have an understanding of what page hierarchy options you can configure. For more information, see Section 22.10, "Creating a Page Hierarchy Using Task Flows."

You may also find it helpful to read about additional functionality that you can add using other task flow features. For more information, see Section 22.1.2, "Additional Functionality for Complex Task Flows."

To create the XMLMenuModel metadata file:

  1. Create an unbounded task flow for each menu in the final page hierarchy.

    For example, to achieve the page hierarchy illustrated in Figure 22-15, you create two unbounded task flows (Human Resources menu and Benefits menu).

    For more information about creating an unbounded task flow, see Section 18.2.1, "How to Create a Task Flow".

    Tip:

    Prefix the name of the file for unbounded task flows that you create with adfc- to help you to identify the file as the source of an unbounded task flow, as opposed to a bounded task flow.

  2. Add view activities that reference pages to each unbounded task flow. The pages referenced by the view activities correspond to the menu nodes in the menu.

    For example, the Benefits menu contains one group node (benefits) and three item nodes (medical, dental and vision) so you add four view activities to the unbounded task flow for the Benefits menu, as illustrated in Figure 22-17.

    Figure 22-17 View Activities on a Task Flow

    Task Flow View Activity

    Do not add view activities for menus that include other menus using shared nodes. For example, the Human Resources menu in Figure 22-15 has a tab called Benefits that references the Benefits menu using a shared node. The bounded task flow for the Benefits menu already includes a view activity for Benefits so there is no need to add a view activity to the bounded task flow for the Human Resources menu.

    For more information about view activities, see Section 19.2, "Using View Activities.".

    Note:

    If the page hierarchy includes pages referenced by a bounded task flow, add a task flow call activity to the unbounded task flow that calls the bounded task flow.

  3. In the Application Navigator, right-click the file(s) for each of the unbounded task flows you created in step 1 and choose Create ADF Menu Model.

  4. In the Create ADF Menu Model dialog, enter a file name for the XMLMenuModel metadata file and a directory to store it.

  5. Click OK.

22.10.1.2 How to Create a Submenu with a Hierarchy of Group and Child Nodes

You open the XMLMenuModel metadata file you created and convert the item nodes that you want to make group nodes to group nodes. You then create a hierarchy where a group node is a parent to one or more item nodes.

Before you begin:

It may be helpful to have an understanding of what page hierarchy options you can configure. For more information, see Section 22.10, "Creating a Page Hierarchy Using Task Flows."

You may also find it helpful to read about additional functionality that you can add using other task flow features. For more information, see Section 22.1.2, "Additional Functionality for Complex Task Flows."

To create a submenu with a hierarchy of group and item nodes:

  1. In the Application Navigator, select and open the XMLMenuModel metadata file.

    An item node appears in the Structure window for each view activity in the unbounded task flow. By default, no hierarchy is defined.

  2. Drag and drop the item nodes to become child nodes of the item node that you are going to convert to a group node.

    Each item node that you convert to a group node must have at least one child item node. For example, to create the menu hierarchy in Figure 22-15, you convert the item node for Benefits to a group node, you drag and drop the item nodes for Medical, Dental, and Vision so that they become child nodes of the Benefit item node.

  3. In the Structure window, right-click the parent item node and choose Convert To groupNode.

  4. Enter a new identifier or accept the default value in the id field of the groupNode Properties dialog that appears

    The identifier must be unique among all of the nodes in all of the XMLMenuModel metadata files. It is good practice to specify a value that identifies the node. For example, if you change the Benefits node to a group node, you can update its default ID, itemNode_benefits, to groupNode_benefits.

  5. In the idref field of the groupNode Properties dialog, enter the ID of one of the other nodes in the menu, for example, itemNode_Medical.

    The value you enter can be an ID of a child item node that is a group node or an item node.

  6. Enter or change the existing default value in the label field to match what you want to appear at runtime.

    For example, you might change label_benefits to Benefits.

  7. Accept the rest of the default values in the fields and click Finish

    A Confirm Convert dialog asks if you want to delete the action and focusViewID attributes on the groupNode element. Group nodes do not use these attributes, always click OK

  8. Click OK

22.10.1.3 How to Attach a Menu Hierarchy to Another Menu Hierarchy

You use a shared node element to link two menus together. For example, the Human Resources menu illustrated in the menu hierarchy in Figure 22-15 contains four submenus (Payroll, Time, Labor, and Benefits). The Benefits submenu is itself a menu with submenu entries. In the XMLMenuModel metadata file for the Human Resources menu, you convert the item node for the Benefits submenu to a shared node. You write an EL expression for an attribute (ref) of the newly-created shared node that references the XMLMenuModel metadata file for the Benefits menu.

Before you begin:

It may be helpful to have an understanding of what page hierarchy options you can configure. For more information, see Section 22.10, "Creating a Page Hierarchy Using Task Flows."

You may also find it helpful to read about additional functionality that you can add using other task flow features. For more information, see Section 22.1.2, "Additional Functionality for Complex Task Flows."

To attach a menu hierarchy to another hierarchy using a shared node:

  1. In the Application Navigator, select and open the XMLMenuModel metadata file for the menu that is going to reference the other menu.

  2. In the Structure window, select a node, right-click and select the appropriate menu options to insert a sharedNode element.

  3. In the ref field of the Insert sharedNode dialog that appears, enter an EL expression to reference the XMLMenuModel metadata file for the other menu.

  4. Click OK.

    Note:

    If your page hierarchy has more than one unbounded task flow, ensure that the file name for each additional unbounded task flow appears as a value for the <metadata-resources> element in the adfc_config.xml file. For more information, see Section 22.10.2, "What Happens When You Create a Page Hierarchy".

22.10.2 What Happens When You Create a Page Hierarchy

Changes occur in a number of different files when you create a page hierarchy.

Changes to the adfc-config.xml File

When you create a new unbounded task flow, JDeveloper automatically adds a reference in the adfc-config.xml file to the source file for the newly-created unbounded task flow. In Example 22-17, adfc-unbounded_tflow.xml is the name of the source file for a newly-created unbounded task flow.

Example 22-17 Unbounded task flow referenced by adfc-config.xml

<?xml version="1.0" encoding="windows-1252" ?>
<adfc-config xmlns="http://xmlns.oracle.com/adf/controller" version="1.2"
             id="__1">
  <metadata-resource id="__2">/WEB-INF/adfc-unbounded_                tflow.xml</metadata-resource>
</adfc-config>

For more information about adfc-config.xml, see Section A.9, "adfc-config.xml".

At runtime, the Fusion web application loads the adfc-config.xml file when it first starts. The adfc-config.xml file can contain:

  • ADF navigation metadata for an unbounded task flow

  • ADF activity metadata for an unbounded task flow

  • Managed bean definitions used by ADF activities

XMLMenuModel Metadata File

JDeveloper generates an XMLMenuModel metadata file with nodes for each of the view activities that you added to the unbounded task flow, as illustrated in Example 22-4.

Example 22-18 Example XMLMenuModel Metadata File

<?xml version="1.0" encoding="windows-1252" ?>
<menu xmlns="http://myfaces.apache.org/trinidad/menu">
  <groupNode id="groupNode_benenfits" label="Benefits" idref="itemNode_medical">
    <itemNode id="itemNode_medical" label="label_medical"
              action="adfMenu_medical" focusViewId="/medical"/>
    <itemNode id="itemNode_dental" label="label_dental" action="adfMenu_dental"
              focusViewId="/dental"/>
    <itemNode id="itemNode_vision" label="label_vision" action="adfMenu_vision"
              focusViewId="/vision"/>
  </groupNode>
</menu>

Diagram for an Unbounded Task Flow

JDeveloper updates the file for the unbounded task flow with the control flow rules and managed beans used to navigate the page hierarchy. Figure 22-18 shows the updated unbounded task flow in the diagrammer that corresponds unbounded task flow in Figure 22-17.

Figure 22-18 Updated Unbounded Task Flow

Updated unbounded task flow diagram.