Skip to main content

Why findNodeByKeyPath() fails while reading selected rows in an af:table

This topic may looks simple for many of you. However some simple mistakes may spoil your entire day. Let me share a point that I learned recently while working with a customer. The requirements was to read all the selected rows from the multi-select table's selectionListener method defined in a managed bean. The code that is initially used for iterating over selected rows was as follows.

Wrong Implementation


 public void wrongAPIForFindingSelectedRows(SelectionEvent selectionEvent) {  
      RichTable _table = (RichTable)selectionEvent.getSource();  
      RowKeySet rks = _table.getSelectedRowKeys();  
      Iterator rksIterator = rks.iterator();  
      //Store original rowKey
      Object originalRowKey = _table.getRowKey();
      try {
         while (rksIterator.hasNext()) {  
           Object rowKey = rksIterator.next();
           _table.setRowKey(rowKey); //stamp row 
 
           //get current node object  
           JUCtrlHierNodeBinding selectedNode =  
                ((JUCtrlHierBinding)  
                ((CollectionModel)_table.getValue()).getWrappedData()).  
                    findNodeByKeyPath((List)rowKey); 
  
           if (selectedNode == null) {  
                System.out.println("selectedNode is null");  
           } else {  
                Row row = selectedNode.getRow();  
                System.out.println("selectedNode in not null" + row.getAttribute(1));  
                // Process row here .......  
           }  
      } finally {
            _table.setRowKey(originalRowKey);
      }
 }  

However the above code failed to return any value for the selected row whenever the selection falls beyond the range size(specified in the page definition file). The reason is that, by design, JUCtrlHierBinding::findNodeByKeyPath(List) API will return null if the nodes that you are trying to find are out of the current range of rows in the tree binding.

Well, now let us take a look at the right implementation(or right API). Solution is to use CollectionModel::getRowData(Object rowKey) API for reading selected nodes. This API, under the cover will go and read row directly from the underlying row set iterator(in fact this change has been introduced recently).

Right Implementation


 public void rightAPIForFindingSelectedRows(SelectionEvent selectionEvent) {  
      RichTable _table = (RichTable)selectionEvent.getSource();  
      RowKeySet rks = _table.getSelectedRowKeys();  
      Iterator rksIterator = rks.iterator();  
      while (rksIterator.hasNext()) {  
           Object rowKey = rksIterator.next();  

            //get current node object...

            //Note: No need to set row currency when you 
            //use getRowData(rowKey). 
            //This method directly fetches the row data
            //from row set iterator. 
           JUCtrlHierNodeBinding selectedNode =  
                (JUCtrlHierNodeBinding)  
                ((CollectionModel)_table.getValue()).getRowData(rowKey);  

           if (selectedNode == null) {  
                System.out.println("selectedNode == null");  
           } else {  
                Row row = selectedNode.getRow();  
                System.out.println("selectedNode in not null" + row.getAttribute(1));  
                // Process the row here ........  
           }  
      }  
 }  

Comments

Anonymous said…
Hi Jobinesh,
This is a good way of getting selected nodes, but this works only with JDev 11.1.2.1.0 (11gR2) because CollectionModel::getRowData(Object rowKey) is available in the latest Trinidad classes.
What is the solution to the issue in JDev 11.1.1.6.0 ? getRowData(Object rowKey) method is not available in 11gR1
Is it okay to get the index of the row and pass it to the available getRowData(int rowIndex)method ?
Nadejda said…
Hi...
Can you help.. I have a tree when Im update seletNode, visual is not updated. can you say why?
tHANKS

Popular posts from this blog

Happy New Year 2018 !

We can't go back and change the beginning, but we always can start where we are and change the ending. Believe in yourself and you will be unstoppable!

Wishing you and your family a very happy new year 2018 !!!

How to set Bind Variable Values at runtime ?

In this post I'm sharing a couple of approaches for programmatically setting bind variables values at run time. This post is an attempt to explain 'When to use what ?'[ In case if you are familiar with 'Bind Variables' in ADF BC, please refer Section 5.10, Working with Bind Variables in Fusion Developer's Guide ]

1. Set the Bind Variable value using RowSet::setNamedWhereClauseParam(...)

You can use use the setNamedWhereClauseParam(...) method on the ViewObject interface (which extends oracle.jbo.RowSet) to set the value for bind variables. Please note this sets the value on default RowSet. In other words, this doesn't have any effect on the secondary RowSets that you/system generates.
ViewObject vo = am.findViewObject("EmployeesView1"); vo.setNamedWhereClauseParam("bindVarDeptId", new Number(10)); vo.executeQuery();
2. Set the Bind Variable value using ViewObject's VariableValueManager::setVariableValue(...)

VariableValueManager Ma…