ADF BC: Pre-filling Transient Attributes in a Child Data Collection of an ADF Page
By Sandra Muller on Jan 24, 2007
In a JHeadstart 10.1.3 project we developed a page with a single parent row and a table of child rows, where the child data collection has a transient attribute. Now that in itself is not such a big deal, but we wanted to set the transient attribute for several rows before showing the data in the page...
We use ADF Business Components (ADF BC) for the Business Service layer,
so the data collections are implemented by ADF BC View Objects (VO's). In our ADF BC Application Module we created a method to loop through the rows of the child VO and set the transient attribute for each. So in order to call this method from our ADF Faces page, we published that method in the ADF BC Application Module, and made sure it is called before rendering the page by adding an invokeAction in the Page Definition. An earlier invokeAction in the same Page Definition sets the correct current row in the parent View Object.
So far, so good. But when we ran the page, the new transient values were not shown in the child table! We tried several ways of looping through the child View Object's rows, and in the end we succeeded. Let me tell you what did not work. It was a good learning experience.
Suppose that the parent VO is called Departments, and the child VO is called Employees.
- We called appModule.getDepartments(), called getCurrentRow() to find the relevant parent row, and on the parent DepartmentRowImpl called getEmployees() to iterate through the child rows of the current Department. We changed the transient attributes, but when we ran the page, the new transient values were not shown in the child table.
Why did this not work? Because DepartmentRowImpl.getEmployees() produces a different row set than is shown in the page, even though they are based on the same View Object! This was explained by Sung Im in 2003(!), and is also described in the ADF Developer's Guide for Forms/4GL Developers: 27.1.3 Understanding View Link Accessors Versus Data Model View Link Instances. See also Steve Muench's Not Yet Documented Example #106.
- We called getEmployees() on the Application Module, and tried to loop through the row set. But the row set was empty, there was nothing to iterate through.
Why did this not work? Because even though the current row was set correctly on the Departments VO, the child Employees were not queried from the database yet. Both invokeActions were executed in the Prepare Model phase of the ADF Page Lifecycle, and the Lifecycle hadn't queried the child rows for the new current parent row yet. Maybe we should try setting the transient attributes in the Prepare Render phase.
- We changed the invokeAction for setting the transient attributes. We set its Refresh property to "renderModel" instead of "prepareRender". Now we did get the right rows to iterate over when calling getEmployees() on the Application Module. But this time, when running the page, no child rows were shown at all.
Why did this not work? Because by iterating over the Employees View Object instance of the Application Module, we influenced the iterator that is used to show the child rows on the page. See the ADF Developer's Guide for Forms/4GL Developers: 27.1.9 Working with Multiple Row Sets and Row Set Iterators
- After calling getEmployees() on the Application Module, we called createRowSetIterator() on the result, to get a new iterator that does not influence the default iterator used in the page.
This time it worked!