Saturday, April 16, 2011

Programmatically refreshing the child nodes of an <af:tree>

There are use cases where you may need to refresh(re-execute the query) the child nodes of a <af:tree> or <af:treeTable> programmatically . In this post I'm discussing a simple implementation for the same.

Query execution for retrieving child nodes

A bit of theory before getting in to the code sample. When you expand top level nodes for the first time, runtime will traverse through the View Link Accessor for the parent Row and identifies the child RowSet/ViewObject and execute the same. The execution of child View Object result in child nodes. When you expand the parent once again, the parent row may find an existing QueryCollection(wrapper object over Rows) with the matching row filter, e.g. say DeptId=10. This existing QC, which already has the filtered list of rows is re-used at this stage. In case you may need to refresh the child RowSet in all cases, you may need to brutally execute the corresponding RowSet. The below shown code snippet executes child Employees RowSet for a specific DepartmentId.

   public void refreshChildEmployees(Number deptId) {  
     ViewObjectImpl vo = getDepartmentsView1();  
     Row[] deptRow = vo.findByKey(new Key(new Object[] { deptId }), 1);  
     String nodeDefname = deptRow[0].getStructureDef().getDefFullName();  
     RowSet childRows = (RowSet)deptRow[0].getAttribute("EmployeesView");  
     childRows.executeQuery();  
   }  

Download

You can download the sample workspace from here.
[Runs with Oracle JDeveloper 11g R1 PS3 + HR Schema]

A glance at the implementation

This example displays tree table for Department-Employee hierarchy. A pop up is given for editing Employee data. You can edit the Employee details and click on the Update button to refresh the corresponding child nodes displayed on the parent page. In the edit pop up, there is a check box(labelled as HiddenFlag) to control the visibility of the corresponding row displayed in the tree table. If you select this check box, row is removed from the corresponding RowSet( which constitutes the child nodes of the tree table).


The EmployeesViewImpl::rowQualifies(...) has been overridden to enable the in memeory filtering for the child nodes . Please see this post in case you are not familiar with this concept. the above given efreshChildEmployees(Number deptId) is wired to the 'update' button which ensure the execution of EmployeesViewImpl::rowQualifies(...) by brutally executing the child RowSet.

Learn More ...

There are a lot more points like this. If  you are curious to learn the internals of the ADF Business Components and ADF Binding Layer,  the following book is for you - Oracle ADF Real World Developer’s Guide.
More details about this book can be found in this post- http://jobinesh.blogspot.in/2012/07/pre-order-your-copy-of-oracle-adf-real.html

5 comments:

sachin said...

Hi,

I just need to execute a custom query on the view object. My query is structured as follows :
select * from mytable
where id in
(select id from mytable
connect by nocycle prior parentid = id
start with id in
(select id from mytable
where attt1=:inp1


... and so on))

Here clauses are set depending on the input values from user.
For example :
if (input=null) clause1=""; (blank)
else clause1=" and upper(att2) like upper(" input ")";

When I give this query in my code, and display the data in a tree, I can only see the parents. When I try to navigate to children of nodes, it is blank. No idea why this is happening. And when I provide these clauses with some predefined values (no bind variables) in design view of VO, it works fine.

I also wonder whether these kind of clauses can be given using setNamedWhereClauseParam() method of VO.

Any idea why is this happening. Am I missing something?

Thanks.

Jobinesh said...

I assume you are using the above said VO for child nodes.If yes try overrunning ViewObjectImpl::prepareRowSetForQuery(ViewRowSetImpl vrs) for child VO to pass the bind parameters- http://jobinesh.blogspot.com/2011/05/preparing-viewobjects-query-for.html

sachin said...

I tried this too, but still same issue. I am not able to see the child nodes.
Please tell me if there is any way by which I can set my clauses in where clause as I mentioned in my original question.

For example :
if (input=null) clause1=""; (blank)
else clause1=" and upper(att2) like upper(" input ")";

then use this clause1 in query.

I tried simply like this :
select ......
where id=:id
|| :clause1

but this didn't work. Any idea why is this happening?

Ravindranath said...

I tried the above code and noticed that it is calling createViewLinkAccessorRS() in VOImpl.java for all the child rows instead of calling it only on the row that we are working on.

Can we do anything to call only the selected row?
Please suggest.

Thanks,
Ravindra

Atul said...

how can we implement the same thing if we are using POJOs and say on click of a Row we then fetch the child details for that row using a pl/sql api and want to re-render/refresh the details for that node?