Core ADF11: UIShell with Menu Driving a Dynamic Region

In this old post in the Core ADF11 series, I explained the various options you have in designing the page and taskflow structure. The preferred approach in my opinion that maximizes flexibility and reusability, is to build the application using bounded taskflows with page fragments. You then have various ways to disclose these task flows to the user. You can use an dynamic tabs as described in this post. You can also embed the taskflows using a dynamic region in a page. The application menu then drives the content of the dynamic region: clicking a menu option will load another taskflow in the dynamic region.

 The initial drawback of this approach is that it adds some additional complexity:

  • You can no longer use standard JSF navigation with your menu, there are no pages to navigate to, only regions
  • The XMLMenuModel, an easy way to define your menu structure in XML, cannot be used as-is. The selected menu entry when using the XMLMenuModel is based on the current page, and in our design, the whole application consists of only one page, the UIShell page.
  • The dynamic region taskflow binding should contain a list of all parameters of all taskflows that can be displayed in the dynamic region.

    This is a rather ugly design, and the developer of the UIShell page would need to know all the parameters of all taskflows that might be displayed in the dynamic region. A cleaner implementation is to use the parameter map property against the taskflow binding. However, when using the parameter map, you need to do the housekeeping of changed parameter values yourself when you want the taskflow to refresh when parameters change. In other words, just specifying Refresh=ifNeeded on the taskflow binding no longer works because ADF does not detect changes in a parameter map.

Fortunately, you can address this complexity quite easily by creating some simple, yet powerful infrastructure classes that hide most of the complexity from your development team. (The full source of these classes can be found in the sample application, download links are at the bottom of this post)

  • A DynamicRegionManager class that keeps track of the current task flow and current parameter map 
  • A TaskFlowConfigBean for each task flow that contains the actual task flow document path, the task flow parameters and a flag whether the parameter values have been changed.
  • A RegionNavigationHandler that subclasses the standard navigation handler to provide JSF-like navigation to a region taskflow.
  • A RegionXMLMenuModel class that subclasses the standard XMLMenuModel class to ensure the proper menu tab is selected based on the currently displayed taskflow in the dynamic region. 

The following picture illustrates how this UIShell concept works at runtime.

The UIShell page (with extension .jsf in JDeveloper 11.1.2 and with extension .jspx in JDeveloper 11.1.1.x) contains a dynamic region. The taskflow binding in the page definition of UIShell gets the currently displayed taskflow from the DynamicRegionManager class that is registered as a managed bean under the name mainRegionManager. The actual task flow id and task flow parameters are supplied by the TaskFlowConfigBean. The DynamicRegionManager manages the current taskflow based on a logical name, for example Jobs. When method setCurrentTaskFlowName is called on the DynamicRegionManager with value Jobs (and we will later see how we use the RegionNavigationHandler to do this), the DynamicRegionManager looks up the corresponding TaskFlowConfigBean by suffixing the Jobs task flow name with TaskFlowConfig.he methods getCurrentTaskFlowId and getCurrentParamMap and currentParamMapChanged then obtain and return the correct values using the JobsTaskFlowConfig bean.

Using this technique, you can configure your dynamic region completely declarative, there is no need to write any Java code. All you need to do is configure the mainRegionManager and task flow config beans, as shown below. 

In this sample, I configured the required managed beans in adfc-config.xml. When using ADF Libraries that contain task flows you want to show in the UIShell dynamic region, it is more elegant to define the TaskFlowConfigBean inside the ADF library. I usually define this bean in the adfc-config file of the task flow itself, below the  <task-flow-definition/> section.  It needs to be outside this section, otherwise the bean cannot be found by the DynamicRegionManager bean that is defined in the unbounded task together with the UIShell page. The advantage of this approach is that the config bean is placed in the same file as the task flow it refers to, the disadvantage is that beans defined outside the </task-flow-definition> section are not visible in the overview tab of a bounded task flow.

To set the current task flow name on the DynamicRegionManager, we use a custom RegionNavigationHandler class that you register in the faces-config.xml.

This class extends the default navigation handler, and overrides the handleNavigation method. The code is shown below. If the outcome contains a colon, the part after the colon contains the task flow name that should be set in the dynamic region.

With this class in place, we can use the action property on command components again to do region navigation, just like we are used to for normal JSF navigation, or navigation between page fragments inside a bounded task flow. The complete flow is as follows:

  • The menu item has the action property set to uishell:Jobs.
  • The region navigation handler set the current task flow name on the Dynamic region manager to Jobs (and navigates to UIShell page if needed) 
  • The dynamic region manager picks up the current task flow id and current parameters from the JobsTaskFlowConfig bean.

The last part of the puzzle is the RegionXMLMenuModel class that subclasses the standard XMLMenuModel class. This class overrides the getFocusRowKey method to return the focus path based on the current task flow region name.

With this class defined in the menu model managed bean, the menu will correctly display the selected tab.   

In a future post I will discuss how the same concepts can be applied to a UIShell page with dynamic tabs.



Hi steven, I'm very impressed and now trying to rebuild your application by myself.
you made DynamicTabs.jsff and it contains declarative component. But when I tried to make declarative component, JDev generate decalrativecomp-metadata.xml and inforce jspx instead of jsff for component ui.
How did you achieve what you made?

Posted by guest on July 12, 2012 at 09:57 PM PDT #

When you use the JDev wizard to create a declarative component, it also creates an entry in declarativecomp-metadata.xml, but this is not needed when you using the af:declarativeComponent tag. It is only used for packaging the declarative component in an ADF library for reuse in other projects.
The extension doesn't really matter, I assume you are using JDev 11.1.1.x instead of 11.1.2.

Posted by guest on July 13, 2012 at 12:59 AM PDT #

Post a Comment:
  • HTML Syntax: NOT allowed

Java EE Consultants - JHeadstart, ADF, JSF


« April 2014