TECHNOLOGY: Oracle ADF
Master and CommanderBy Frank Nimphius
Implement a reusable command pattern template strategy using contextual events for unlimited parent-to-region interaction.
An Oracle Application Development Framework (Oracle ADF) region is an aspect of the Oracle ADF Controller that executes bounded task flows in defined layout areas within a view, page, or page fragment, without forcing a refresh of the entire view. Think portlets and you have the right idea.
There are many ways to establish communication between a view and a bounded task flow exposed in an Oracle ADF Region. These Oracle ADF Region interaction strategies include contextual events, data exchange via input parameters, managed bean injection, shared Oracle ADF data control, and many others. Developers should choose an interaction strategy that best suits the use case they want to implement.
One common Oracle ADF Region use case that frequently appears on the Oracle Technology Network Oracle JDeveloper forum is a global toolbar or menu bar within a parent view. The goal is to have the global toolbar perform actions, such as data iteration, create/update/delete operations, or context-sensitive help display, on the view displayed in a separate region.
This article will show how to implement this use case by borrowing the idea of the command pattern from object-oriented programming. A command pattern implementation, deployed as an Oracle ADF library, is provided for you to use within your custom development projects.
An Advanced Topic
Unlike previous Oracle Magazine articles, which were more suitable for beginners, this article covers an advanced topic in Oracle ADF task flow communication. It’s assumed that you have an understanding of core Oracle ADF technology concepts such as bounded task flows, task flow templates, Oracle ADF Regions, page templates, and the Oracle ADF binding layer.
The Problem Statement
The use case for this article is comparable to a universal remote control that, independent of the receiving device, always issues the same set of commands.
Using this analogy, the receiving device in Oracle ADF is the current view displayed in an Oracle ADF Region. The remote control in this scenario is a toolbar or menu bar, in the parent view, that sends commands into the Oracle ADF Region to process in the context of the current view. The commands passed from the parent view to the region continue working even when the current view changes due to users navigating within the task flows. The interpretation of a given command, however, may be different; it is up to each receiving region to react properly to the signals from the parent view.
A Command Pattern Solution
The command pattern is a well-known design pattern in object-oriented programming that uses a command object to encapsulate all the information needed to invoke methods on other objects. The command pattern describes three acting parts: a client that creates the command object, including information about the actions to invoke on a target object; an invoker that dispatches the command defined in the command object; and a receiver that represents the target object on which the command is executed.
With slight variations applied to the invoker and receiver, the command pattern defined for object-oriented programming can be used with Oracle ADF and task flows to implement the Oracle ADF Region interaction use case covered in this article.
In Oracle ADF, the invoker object is replaced by contextual events. They take a payload (command object) defined by the client and broadcast it as an event to registered listeners (receiver). The event receiver does not execute commands directly; instead, it further dispatches the execution to a managed bean loosely coupled with the current view. For example, in Figure 1, Action 1 and Action 2 are managed beans whose roles are to interpret incoming action requests and to execute the appropriate methods for the view.
Figure 1: Technical implementation outline
Figure 1 shows a simplified architecture of the command pattern, as implemented with Oracle ADF. In this architecture, the buttons in the parent view represent the command pattern client. When a button is pressed, it creates a payload object (command object) that includes the name of the action to invoke in the context of the view displayed in the region, along with optional additional information developers may want to provide to the receiving end. The event receiver in the Oracle ADF Region is a data control method that is referenced in the PageDef file (binding container definition) of each view.
The solution in Figure 1 retains task flow encapsulation and does not expose objects located within the task flow to the outside consumer. One change to the command pattern in object-oriented programming is that the Oracle ADF Region container allows developers to check for commands supported by the current view to let them disable or hide command buttons accordingly.
The Command Pattern Implementation
The code sample for this article is packaged by implementing the command pattern design for Oracle ADF Region interaction in a separate Oracle JDeveloper workspace. This code is deployed into an Oracle ADF library and can be used in the sample application provided as well as in your own custom applications.
Figure 2 provides an overview of the command pattern implementation. Both sides of the command pattern implementation, the client (producer) and the receiver, are developed as page templates. Each page template has its own Oracle ADF binding file (PageDef) defined. The PageDef file of the producer page template contains the contextual event metadata that defines the event name, the action type to listen for, and a reference to the location of the payload object.
Figure 2: Task flow command pattern template architecture
The PageDef file associated with the receiver page template contains the event handler definition and a mapping that binds the producer event name with it. A lifecycle configuration in the form of an Oracle ADF Region Controller is used to let the calling side (producer) know the action commands supported by the current view (receiver).
A task flow template is provided for any implementing receiver task flow to consume. The task flow template ensures that the required managed beans and input parameters are configured on the receiving task flow and exposed to the Oracle ADF application developer.
The public APIs exposed to the application developer by the task flow command pattern template consist of two page templates, a task flow template, and a set of abstract classes for the developer to extend.
With the provided sample implementation, the assumption is that the view action handlers shown in Figure 1 are implemented as JavaServer Faces (JSF) managed beans in backing bean scope within the bounded task flow.
The name of the managed bean should be the same as the view activity, along with a prefix of tfcp, which stands for task flow command pattern. So if the view activity name is DepartmentsView, then the associated backing bean name configured in the task flow configuration file should be tfcpDepartmentsView.
A third pillar in this architecture is a set of implementation classes containing logic to invoke, dispatch, and handle the defined contextual events. Following the Oracle ADF framework naming convention, these classes are stored in a package structure starting with “internal.” Application developers don’t need to know about these classes and should not have any need to use them.
Before exploring how the task flow command pattern solution works, you should first download the command pattern sample application and unzip the o62adf-1841823.zip file to a local folder on your computer. To open the sample application, you need the studio edition of Oracle JDeveloper 11g Release 2 (184.108.40.206.0), available as a free download on Oracle Technology Network. You also need an Oracle database instance with an unlocked HR schema.
The sample application contains two folders:
To run the sample application, you also need to change the database connection to point to your HR database schema:
As another preliminary task, start the Oracle WebLogic Server instance integrated with Oracle JDeveloper. To start the Oracle WebLogic Server, select Run -> Start Server Instance (IntegratedWebLogicServer).
If this is the first time you’ve run the integrated Oracle WebLogic Server, a Create Default Domain dialog box will open. Create a password for the default Oracle WebLogic Server domain, and select an address from those listed for Listen Address. For example, choose localhost rather than leaving the address empty.
Click OK to save the change and create and configure the default domain for Oracle ADF.
Sample Application Overview
With the OraMagSample workspace open, expand the ViewController node to see a project view similar to what is shown in Figure 3.
Figure 3: Sample application ViewController project
Figure 4 shows the architecture of the sample application, with the task flow command pattern template library parts colored in green.
Figure 4: Sample application architecture
The sample application contains a single JSF document, ParentView.jspx, that is based on the event-producer-template.jspx page template defined in the TaskFlowCommandStrategyLib.jar library.
In Oracle ADF, views that are based on a template not only adopt the template layout definition but also maintain a reference to the template Oracle ADF binding file (if the template has its own Oracle ADF binding).
The event-producer-template.jspx file, upon which the ParentView.jspx document is based, has a PageDef file defined and configured as a contextual event producer. Because the ParentView.jspx document maintains a reference to the template binding, it can broadcast contextual events as indicated in Figure 4.
The event-producer-template.jspx file does not contain layout definitions; it only helps to automate the registration of views as a contextual event producer. Luckily, Oracle JDeveloper 11g Release 2 lets application developers nest page templates. As a result, an Oracle ADF Faces view built based on a functional template can contain additional page templates to improve look and feel.
In the OraMagSample application, the ParentView.jspx page uses a nested template reference to the default Oracle three-column template.
Also shown in Figure 4, the ParentView .jspx template uses two managed beans in viewScope that are configured in the adfc-config.xml file located in the Web Context ->public_html->WEB-INF folder.
The SupportedToolbarActions bean is passed as an input parameter value to the bounded task flow, also shown in Figure 4. The bounded task flow uses this bean reference to call back into the parent view. In the sample application, the callback is used to change the button bar disabled state depending on the view currently displayed in the bounded task flow.
Let’s have a detailed look at each of the two beans:
The region navigation listener receives a notification each time the view displayed in the bounded task flow changes. This notification is used to refresh the button bar by disabling a button if its action is not supported by the new view.
The command receiver in the sample application consists of a bounded task flow that is created from the library command-receiver-flow-template.xml, as well as views that are built based on the event-receiver-template.jspx page template in the TaskFlowCommandStrategyLib.jar.
Similar to event-producer-template.jspx for the parent view, event-receiver-template .jspx automatically configures the views in the bounded task flow for contextual events. This time, however, the views are configured as contextual event receivers, as shown in Figure 4.
The departments-employees-flow.xml bounded task flow definition located in the Web Content -> WEB-INF folder defines two managed beans used as view action handlers to receive contextual event notification, as well as two backing beans used to access and launch a dialog box contained in the view.
Let’s look at two representative beans in more depth:
To see this configuration defined for the ParentView.jspx file in the sample application, expand the Application Sources node in the ViewController project and navigate to the ParentViewPageDef.xml file located in the oramag.novdec.twelve.sample.view pageDefs package. To open the page definition file, right-click the ParentViewPageDef.xml file and select Open from the context menu. In the binding editor, click the Source tab at the bottom to switch to the source view.
Running the Sample
To run the sample, right-click the ParentView .jspx file in the Application Navigator and select Run from the context menu.
The application opens in a browser showing a global button bar and an edit form for the HR Departments table. The button bar resides in the ParentView.jspx file, while the edit form is defined in the DepartmentsView.jsff page fragment in the bounded task flow (Oracle ADF Region). Note that the departments edit form does not implement query functionality. As a result, the Execute Query button is disabled, as shown in Figure 5.
Figure 5: Runtime view of sample application
Clicking any of the buttons in the button bar issues a contextual event that is broadcast to the view in the bounded task flow. The contextual event handler checks the discriminator value passed with the event request. If the value matches the value configured in the task flow, it invokes the command on the view action handler.
To navigate to the employees form, click the Navigate to Employees button. Upon task flow navigation, the region navigation listener on the af:region tag is invoked for the parent view to refresh the button bar with the capabilities of the employee view. As a result, the Execute Query button becomes enabled. As you would expect from a command pattern implementation, the same set of buttons now operate on the employees view.
This article outlines a solution for a frequently asked-about use case in Oracle ADF Region interaction by providing an implementation that can be reused in many projects.
The task flow command pattern template library contains page templates, a task flow template, and a public API that simplifies the configuration of this solution in custom projects. The contextual event implementation detail in the template is hidden from the application developer.
In addition, this article has shown how to adopt the command design pattern from object-oriented programming for use within an Oracle ADF development environment.
Frank Nimphius is a senior principal product manager for Oracle JDeveloper and Oracle ADF. He is a coauthor of Oracle Fusion Developer Guide: Building Rich Internet Applications with Oracle ADF Business Components and Oracle ADF Faces (McGraw-Hill, 2010).