Automatic Master Detail Synchronization with ADF Faces
Written By Duncan
Mills, Oracle Corporation
April, 2006
Introduction
A common question when building complex screens using ADF is how to
automatically synchronize the contents of related data-sets
when
a master detail is selected in a table. For example the application may
have a master collection of DEPARTMENTS records displayed in a table,
and the intention is that clicking on the selection radio button in the
tables selectOneChoice component should be enough to cause the
associated EMPLOYEE records to display automatically without any extra
action on the part of the user.
Setup
For the purposes of this how-to we'll be using ADF Business Components
as the persistence technology. ADF Business Components handles the
master detail coordination from the data point of view for us. In this
case we're working from a starting point of two view objects
based
on the DEPARTMENTS and EMPLOYEES tables from the Oracle HR schema.
These two view objects are linked using a view link which
describes the one to many relationship between a department and its
employees. This view link will take care of the coordination. The
DEPARTMENTS view object is exposed via the application module, and the
employees view object is exposed both directly under the application
module and the view link to nest it with the departments view object. Figure 1: The
MasterDetail Application Module
Using this ADF Business Components project as the model for the example
the Data Control Palette will look like this: Figure 2: The Data
Control Palette
Defining the UI
The user interface that we'll create in the first example will be a
single JSF page containing two tables. The upper table being read-only
and containing the available departments, the second lower table being
the employees within the selected department. At runtime the screen
will look like this: Figure 3: Departments /
Employees master detail
Steps to create this UI
To create this screen carry out the following steps:
Drag the AllDepartments
collection from the Data Control Palette and drop it onto the page as Tables > ADF Read Only
Table...
In the Edit
Table Columns dialog, check the Enable selection
checkbox to add the tableSelectOne component into the selection facet
of the table.
In the Data Control Palette, expand the AllDepartments node
and select the EmployeesByDept
collection.
Drag and drop this collection onto the page underneath the
departments table. Drop it as Tables
> ADF Table...
In the Edit
Table Columns dialog, Remove all of the columns except for
EmployeeId, FirstName, LastName and Email using the Delete button and
OK the dialog.
The basic screen is now complete and can be run. Notice that as you
click the radio buttons in the table of departments, the contents of
the lower table do not change. To make the contents change you will
need to make a selection in the table, and then click the Submit button.
Note: the screen shown in Figure 3 has some extra panelHeader
components and a panelBox to dress up the UI a little. To get this more
polished version of the screen download the workspace from here.
Setting Up Synchronization
The next task is to eliminate the requirement for the Submit button to
be pressed to make the employees table update:
In the Structure window, locate the department
table. Bring up the Property Inspector and set the Id property to DepartmentTable.
This Id for the table is needed for the second table to be able to
notified of changes.
Expand the table definition and locate the af:tableSelectOne
component inside of the selection facet. Set the AutoSubmit property
of this component to true.
This means that as soon as the radio button in the selection column is
pressed a partial page submit will be sent to the server which will
change the row currency in the departments iterator.
Locate the employee table in the Structure Window and set
the PartialTriggers
property to DepartmentTable. A pop up dialog appears to help you with
this; Press [...],
then the New
button in the dialog, and then select DepartmentTable from the pull
down list that appears in the list labeled List Items.
This is the important step. Although we have caused the page to submit
in Step 2, it is only a partial submit, the whole page has not been
refreshed so the second table is not updated to reflect the new master.
Setting the PartialTriggers property tells the employee table to
"observe" the DepartmentTable component (hence the need to give the
department table an ID to identify it with). When a change happens to
the master table, any other components that are observing it using the
PartialTriggers mechanism
(Optional) Go back to the department table and set it's Immediate property
to true.
Making the table immediate will mean that any changes in the employee
table will be thrown away as the departments list selection
is
changed.
Now when you run the page you should get the synchronization without
having to press that submit button at all.
Master - Self Synchronization
Another similar scenario when synchronization is important, is the use
of a table to select a record in a collection for editing. In the
example here the AllEmployees collection is navigated through using the
table. Selection in the table selects the row to edit on the form. Both
the table and the form controls are based on the same iterator. Figure 4: Row Selection
Using A Table
Creating the UI
Drag the AllEmployees
collection onto a new page and drop as a as Tables > ADF Read Only
Table...
In the Edit
Table Columns dialog, check the Enable selection
checkbox to add the tableSelectOne component and delete most of the
columns so that the table just shows the FirstName and LastName
attributes
Now select the AllEmployees
collection again and drop it as a Form onto the page underneath the
Table.
If you run the page as it stands, synchronization will be delayed until
the Submit button is pressed.
Managing the Synchronization
Setting up auto synchronization is very similar to the last case:
In the Structure window, locate the employee
table. Bring up the Property Inspector and set the Id property to EmployeeTable. This
Id for the table is needed for the form to be able to notified of
changes.
Expand the table definition and locate the af:tableSelectOne
component inside of the selection facet. Set the AutoSubmit property
of this component to true.
This means that as soon as the radio button in the selection column is
pressed a partial page submit will be sent to the server which will
change the row currency in the employees iterator.
Locate the <af:panelForm>
containing the employee form fields table in the Structure
Window and set the PartialTriggers
property to EmployeetTable. In this case, by setting the PartialTriggers
property on a container, all of it's children will be updated when the
object that it is observing changes.
(Optional) Go back to the employee table and set it's Immediate property
to true.
Making the table immediate will mean that any changes in the form will
be thrown away as the employee selection is
changed.
Summary
This how-to has show you how the combination of auto-submit
on a
tableSelectOne facet, in combination with the PartialTriggers property
on components can be used to create interactive master detail pages.
Using the techniques outlined here only the changing portions
of
the page are updated in an Ajax-Style transaction with the server, as
opposed to the entire page having to be re-fetched. A
complete workspace containing working versions of the pages we've
discussed can be downloaded here.