Skip to main content

Triggering Navigation from a Contextual Event Handler Method

ADF task flows are key building blocks for a Fusion Web Application. You can render a bounded task flow in a page using ADF region. Often a parent page may need to trigger navigation within the embedded region while responding to specific user actions. This blog post discusses such a use case scenario and a possible solution for the same.

Consider a generic case where a JSF page contains a bounded task flow added as a region. Here the requirement is that when user selects specific option displayed on the parent page, the ADF region's content(taskflow view activity) should navigate to an a new view/page. Let me try to explain this scenario with a more realistic example. Please see the following diagram. You may notice that deptemp-task-flow-definition is added as region to a page and the this page is having two buttons to edit the department and employee details. On clicking these buttons on parent page, the 'embedded' deptemp-task-flow should navigate to the corresponding edit page.

The following steps outline the implementation at a high level.

1. Defining Contextual Event and associate this with an actionListener for the command button.
2. Defining Event Consumer and perform event mapping between producer and consumer.
3. Triggering the navigation based on event payload.

In this post I'm discussing only the 3rd step from the above list. Please refer 28.7 Creating Contextual Events in Fusion Developer's Guide, in case you are not familiar with Contextual Event and it's usage.

Triggering Navigation from the Contextual Event

Please note that, as of now there is no declarative way to navigate to a different view (conditionally) from a contextual event handler method. One possibility is to handle the navigation programmatically.


JSF lets you toqueue FacesEvent on UIComponent manually. The approach I'm following in this example is driven by this idea. If you have proper navigation sequence defined in the task flow, then this is going to be an easy task. In the current example, there are two CommandButtons defined on the default view for deptemp-task-flow. One for editing dept details, and the second one for emp details. As you might have imagined, these two buttons have action defined for navigating to edit view. Now the solution is pretty simple and straight forward - queue the ActionEvent on the appropriate button component (RichCommandButton) from the contextual event handler method. This may trigger the desired navigation at proper JSF life cycle phase(Invoke Application). Please see the code snippet copied below to get a feel of this approach.

 * Handler(subscriber) for the Contextual Event
public void handleEvent(String arg) {

  String compId = null;
  if (arg.equals("editDept")) {
    compId = DEPT_EDIT_BTN_ID;
  } else if (arg.equals("editEmp")) {
    compId = EMP_EDIT_BTN_ID;

  if (compId != null) {
    RichCommandButton btn = getEditButtonComponent(compId);
    ActionEvent actEvent = new ActionEvent(btn);


Before winding up this discussion, let me answer one query that may arise in your minds :)
Why don't you use javax.faces.application.NavigationHandler
) here?

Well, this works...but this may have it's own side effects. The call to NavigationHandler.handleNavigation(...) bypasses JSF life cycle phases and forcefully triggers the navigation. So you may see some unexpected results in certain scenarios.

You can download the sample workspace from here.
[Runs with Oracle JDeveloper 11g R1 PS2 + HR Schema]

A glance at the implementation

The entry point for this sample application is main.jspx. This page contains two buttons('Edit Dept' and 'Edit Emp' ) on top, and a task flow(deptemp-task-flow-definition) displaying department employee details.

The deptemp-task-flow-definition at glance:

1. This task flow has 'deptEmp' view as the default activity.
2. The 'deptEmp' view contains two CommandButtons namely 'Dept Details' and 'Emp Details'. Clicking on these button would take you to corresponding edit screens. Please note that we would be using these buttons for queuing the ActionEvent to trigger the navigation from contextual event handler method.

Please run the main.jspx. When you click on 'Edit Dept' or 'Edit Emp' buttons displayed on top, the action in turn triggers contextual event('editEvent') defined on the main page. The 'deptEmp' view on the deptemp-task-flow has been registered as a subscriber for this event. As we discussed earlier, this subscriber method queues an Action Event on the CommandButton defined on the deptEmp view('Dept Details' / 'Emp Details' buttons). This result in the navigation to the editDept/editEmp view at proper phase of JSF life cycle.


Hi Jobinesh, great post! I actually had a use case where I captures a hoover over behavior on JS and then navigated to another region. For this one the queue on JSF was the only one that worked. NavigationHandler didn't help

Here s the article, however it is in Spanish.

Juan C.
Jobinesh said…
Cool..thanks Juan for sharing this.
Anonymous said…
Very Nice. Thanks a Lot.
Binu said…
Hi Jobinesh,

I got a situation as follows:

I got a three Task Flows created. ParentTaskFlow, ChildTaskFlow1, ChildTaskFlow2
In the ParentTaskFlow Jsff page I got 2 buttons

1. BUTToN1_ChildTaskFlow1
2. BUTToN2_ChildTaskFlow2

And a ROUTER to Both the child flows

So when I click on button1 it should flow to ChildTaskFlow1 which is set as 'defult outcome' for router
and it works fine.

But when I click on button2 how do i route to ChildTaskFlow2 ?

Please help me.

Binu Mathew

Popular posts from this blog

How to set Bind Variable Values at runtime ?

In this post I'm sharing a couple of approaches for programmatically setting bind variables values at run time. This post is an attempt to explain 'When to use what ?'[ In case if you are familiar with 'Bind Variables' in ADF BC, please refer Section 5.10, Working with Bind Variables in Fusion Developer's Guide ]

1. Set the Bind Variable value using RowSet::setNamedWhereClauseParam(...)

You can use use the setNamedWhereClauseParam(...) method on the ViewObject interface (which extends oracle.jbo.RowSet) to set the value for bind variables. Please note this sets the value on default RowSet. In other words, this doesn't have any effect on the secondary RowSets that you/system generates.
ViewObject vo = am.findViewObject("EmployeesView1"); vo.setNamedWhereClauseParam("bindVarDeptId", new Number(10)); vo.executeQuery();
2. Set the Bind Variable value using ViewObject's VariableValueManager::setVariableValue(...)

VariableValueManager Ma…