Targets, Accessors, and TreesBy Steve Muench
Hierarchical data displays are simple with Oracle Application Development Framework.
A tree control offers end users an intuitive way to explore relationships in the data you present. In this column, you’ll see how easy it is to create tree-based hierarchical data displays with Oracle Application Development Framework (Oracle ADF). By following the steps in this column, you’ll create a tree-based display of the EMP table’s employee management hierarchy. Then, by using declarative support for synchronizing a target view object, you’ll make it possible for users to see additional information about any employee by selecting that employee’s node in the tree.
To begin, download the starter workspace and ensure that you’re using the studio edition of the Oracle JDeveloper 126.96.36.199 (production) release, available as a free download on Oracle Technology Network (OTN). Start by extracting the contents of the o49frame.zip file, and open the FrameworksJulAug2009.jws workspace in Oracle JDeveloper. The Model project in the workspace defines a base set of Oracle ADF components for working with the data in the EMP table in the SCOTT schema. Before proceeding, adjust the properties of the connection named scott in the Application Resources zone of the Application Navigator until you can successfully test a connection to the SCOTT schema. If necessary, use the provided CreateDeptEmpTables.sql script to create the schema’s tables.
From View Links, a Tree Grows
View links connect view objects into master/detail hierarchies. (For more information, see “ Working with Master/Detail Data,” Oracle Magazine, November/December 2005.) This makes them a natural ingredient in the Oracle ADF recipe for tree-based data display. When a user selects a master row in a simple master/detail page, the detail area refreshes to show the rows related to that master. A tree’s data access requirements are more complex, because the tree can have any number of root nodes and the end user can expand any set of nodes to any depth at any time. Rather than managing one master row with one detail rowset at a time, a tree manages many nested rowsets in support of each expanded branch in the tree.
Whenever you define a view link, Oracle ADF enables an additional attribute in the source view object called the view link accessor attribute . This attribute’s value is the rowset of detail rows related to the current master row. View link accessor attributes play an essential role in defining and materializing the nested data of the expanded nodes in the tree at each level.
You can show the data from any set of view-linked view objects in a tree by following three basic steps. First, you choose a view object in the application module’s data model and drop it onto the page as a tree control. The rows from this view object instance provide the root nodes in the tree. Next, you decide which attributes will display in the tree for that view object’s rows. Third, you define which view link accessor attributes provide the nested detail rows you want to include.
The sample workspace includes an interesting case of a master/detail relationship: the recursive one represented by the management hierarchy of employees. The WorksForMgrLink view link uses the EmpView view object as both its source view and its target view. Follow the steps below to see how simple it is to build a tree to display the management hierarchy.
Creating the Tree
Start by double-clicking the WorksForMgrLink view link in the Application Navigator ( Model -> Application Sources -> oramag.model -> WorksForMgrLink ) to open it in the View Link Editor. Select the Relationship tab, and in the Attributes section, note that the source and destination attributes reference the underlying WorksForMgrAssoc entity association. This association already defines the one-to-many relationship between one Emp entity and the zero or more Emp entities that work for that manager. The view link reuses this relationship without needing to redefine the source and target attribute pairs.
As with any attribute, it’s important to pick a meaningful name for the view link accessor attribute to clarify its purpose to colleagues who might help maintain the application. In the Accessors section of the editor, next to the Destination heading, note that the current name of the view link accessor in the EmpView view is EmpView_2. Click the pencil icon to the right of the Accessor section header to edit the view link accessor names. In the View Link Properties dialog box’s Destination Accessor section, enter DirectReports for Accessor Name and click OK to return to the editor.
In the Application Navigator, double-click the EmployeeHierarchy.jspx page ( ViewController -> Web Content -> EmployeeHierarchy.jspx ) to open the page in the visual editor. The page already contains a decorative box and a panel splitter control that divides the page vertically into two content sections called facets in JavaServer Faces (JSF) parlance. Now expand the Application Navigator’s Data Controls section, and then expand the HRModuleDataControl . The HRModule application module contains a view object instance of EmpView named EmployeeHierarchy , which you can see in the Data Controls section as a data collection ready for drag-and-drop data binding. Drag the EmployeeHierarchy data collection, and drop it into the center of the first facet, on the left side of the splitter. When the Create menu appears, choose Trees -> ADF Tree to show the employee hierarchy data as a tree component.
When the Edit Tree Binding dialog box appears, note that the EmpView view object’s fully qualified name is the first entry in the Tree Level Rules list. Also note that the Empno attribute is in the Display Attributes list at the bottom.
If you were to leave things like this, the tree would display employee IDs, but you’ll use the employee name instead. Select the Empno attribute in the Display Attributes list, and click < to remove it. Then select the Ename attribute in the Available list, and click > to add it. Click the green plus sign in the Tree Level Rules header area. The menu that appears presents the names of any view link accessor attributes for the currently selected tree-level rule. Because the selected tree-level rule is based on the EmpView view object, the menu contains the names of that rule’s view link accessor attributes. Note that the only one there is the DirectReports view link accessor attribute you renamed earlier. Select it in the list, and note that the name of the tree rule is updated to include <DirectReports> to give you feedback on how the tree-level rule will drill down to access detail rows. Because this is a recursive example, the rows in the DirectReports view link accessor rowset will also be of type EmpView , so only a single, recursively applied tree rule is needed. (Had the view link been to a destination view object of a different type—for example, a hypothetical CurrentJobAssignmentsView —a new tree-level rule would appear automatically for that type, and you could configure its display attributes as appropriate.) For each tree-level rule, you select one or more view link accessor attributes to define the access path to the next level(s) down in the tree, depending on how much and which parts of a view-linked view object hierarchy you want to display to the end user. Finally, click OK to create the data-bound tree component.
Configuring Root Nodes
To test the page, right-click the EmployeeHierarchy.jspx page in the Application Navigator and choose Run . When the page appears in your browser, the tree shows all 14 employees at the root. Expand the node for KING , and note that BLAKE appears as one of KING ’s direct reports. BLAKE also appears as a root node in the tree. This could be confusing to the end user, so next you’ll configure a view criteria to apply to the view object instance. It will filter the employee rows that appear at the root of the tree to show only the employees who have a NULL value for their Mgr attribute.
In Oracle JDeveloper, double-click the EmpView view object in the Application Navigator ( Model -> Application Sources -> oramag.model -> EmpView ) to open it in the editor. Select the Query tab, and in the View Criteria section at the bottom, click the green plus sign to create new view criteria. When the Create View Criteria dialog box appears, enter TopLevelManagers for Criteria Name and click the Add Item button below to add a view criteria item. With the new view criteria item selected in the Criteria Item section at the bottom left, choose Mgr for Attribute and Is Blank for Operator . (You might need to scroll through the list to see it.) Then click OK to define the new view criteria.
Next, you’ll configure the EmployeeHierarchy view instance in the data model to use the new view criteria to filter its rows. Double-click the HRModule application module in the Application Navigator ( Model -> Application Sources -> oramag.model -> HRModule ) to open it in the editor. Select the Data Model tab, and then select EmployeeHierarchy in the Data Model list. Click the Edit button to edit its view instance properties. When the Edit View Instance dialog box appears, select the TopLevelManagers view criteria in the Available list and click > to move it into the Selected list. This view criteria will now be used to filter the root data collection for the tree. Click OK to dismiss the dialog box, right-click the EmployeeHierarchy.jspx page in the Application Navigator, and select Run . When the page appears in your browser this time, note that only the top-level managers show up at the tree’s root—in this case, only KING qualifies. Try expanding nodes to reveal whichever parts of the management hierarchy you’d like to see. Editing the view instance in the data model to apply the view criteria there affects only the rows that appear at the tree’s top level. The filter doesn’t affect other nested details that the tree accesses by using view link accessor attributes.
Targeting Another Iterator on Tree Selection
In addition to helping end users explore and understand the data hierarchy, the tree component offers a simple way to select, inspect, and act on a particular row of data. Next, you’ll enhance the tree you’ve created to show the full set of employee information for the selected employee. You’ll do this by dropping a read-only form and configuring the tree to automatically synchronize the iterator on which the form display is based with the selected node in the tree. It is a best practice to use one view object instance for the tree display and a second instance for any eventual detail data display or editing. This approach enables the query for the tree to retrieve the minimal data required for the tree display, whereas the more detailed set of data is queried only as needed on the rows the user selects.
Start by adding a second instance of EmpView to the data model. On the Application Module Editor’s Data Model page ( HRModule.xml, Data Model tab), select the HRModule root node in the Data Model list. In the Available View Objects list, select the EmpView that appears as a root node—the one whose label is simply EmpView , not the one indented beneath it labeled EmpView via WorksForMgr . Change the value in the New View Instance field (below the Available View Objects list) to be EmployeeDetail , and then click > to add a view instance of this name to the data model.
Because you want this new instance to show data only when the automatic tree selection synchronization occurs, you need to configure it not to perform its normal query. (Otherwise the form would display the first row in the employees table when the page first renders, which you want to avoid.) With the EmployeeDetail view instance selected in the Data Model tree, click the Edit button. In the Edit View Instance dialog box, select the Tuning page from the list at the left, and in the Retrieve from the Database section, select the No Rows option. Click OK , and choose File -> Save All to save your changes.
Next, you’ll add a form display based on this new view instance. Click the EmployeeHierarchy.jspx tab to return to the visual editor. In the Data Controls section of the Application Navigator, you should see the new EmployeeDetail data collection. (If you don’t see it, right-click HRModuleDataControl and choose Refresh .) Drop the EmployeeDetail data collection onto the center of the second facet, on the right side of the splitter. When the Create menu appears, choose Forms -> ADF Read-Only Form . In the Edit Form Fields dialog box, click OK to accept all the fields, leaving the Include Navigation Controls and Include Submit Button check boxes unchecked.
Now you need to configure the tree binding’s target iterator property. Select the Bindings tab at the bottom of the visual editor. Then select the EmployeeHierarchy tree binding in the Bindings box, and click the pencil icon in the box header to edit it. Ensure that the EmpView rule is selected in the Tree Level Rules list, and then at the bottom of the Edit Tree Binding dialog box, just above the Help button, expand the Target Data Source header. Click the EL Picker button to select an EL expression that identifies the target iterator you want to synchronize with the selection of any EmpView node in the tree. In the EL picker dialog box, expand the ADF Bindings folder and the bindings node inside it. Select EmployeeDetailIterator from the tree, and note that an EL expression identifying this iterator appears in the Expression text box above. Finally, click OK to use this EL expression for the target iterator property’s value, and then click OK to dismiss the Edit Tree Binding dialog box. At runtime, when the end user selects a node in the tree whose tree-level rule has a target iterator expression defined, Oracle ADF will automatically perform a setCurrentRowWithKey operation on the target iterator, using the key of the newly selected row.
Finally, configure Employee DetailIterator to use the automatic partial-page rendering you learned about in “ Easier Interactive Data Entry ” ( Oracle Magazine , January/February 2009). This causes the fields in the form to refresh automatically, with the data reflecting the new tree selection. Select EmployeeDetailIterator in the Executables box. In the Property Inspector, expand the Advanced header and set ChangeEventPolicy to ppr . Now run the EmployeesHierarchy.jspx page again. When the page appears, you’ll see that when you select a node in the tree, the selected employee’s detail information is displayed in the form at the right (as shown in Figure 1).
Armed with the knowledge you’ve gained here, you’re ready to begin using tree controls in your applications. For more information on how tree data access differs from normal master/detail coordination, see section 35.1.3, “Understanding View Link Accessors Versus Data Model View Link Instances,” in Oracle Fusion Middleware Fusion Developer’s Guide for Oracle ADF 11g.
Steve Muench is a consulting product manager for Oracle JDeveloper and an Oracle ACE. Since 1990 he has developed and supported Oracle tools and XML technologies and continues to evangelize them. Muench coauthored Oracle ADF Developer’s Guide for Forms/4GL Developers (Oracle, 2006), wrote Building Oracle XML Applications (O’Reilly Media, 2000), and shares tips and tricks on OTN and in his “ Dive into ADF” blog.