Friday, August 3, 2018
Why findNodeByKeyPath fails while reading selected rows in an af table
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 tables selectionListener method defined in a managed bean. The code that is initially used for iterating over selected rows was as follows.
Wrong Implementation
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
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 ........
}
}
}