How to refer to an Attribute in the Currently Selected Table row in an ADF Faces page – implementing a Generic Row Reader

A very small article on a very trivial issue. I have a page with a Master-Detail construction with a (master) Table of Departments and a (detail) Table of Employees. My challenge here: how can I display the name of the currently selected Department in the heading for the Employees table? Using ADF Bindings, this should be dead easy? And indeed: it is.

How to refer to an Attribute in the Currently Selected Table row in an ADF Faces page - implementing a Generic Row Reader showdetail incustomizablepanel

The steps:....

1. First identify the iterator used for the Departments table:

<af:table value="#{bindings.DeptView1.collectionModel}" var="row"

2. Then create the reference to the current row in this iterator and the required attribute in that row: 

... text="Employees in the selected Department #{bindings.DeptView1.currentRow.dname}" 

3. However,  the Row that is returned here is the generic ViewRowImpl class. That class has no getDname() method, only a generic getAttribute() method.

The most direct (though least generic) solution here is to generate the specific DeptViewRowImpl class, by checking the appropriate checkbox on the ViewObject wizard:

How to refer to an Attribute in the Currently Selected Table row in an ADF Faces page - implementing a Generic Row Reader deptview rowimpl 

Alternatively, we can create our own AMISViewRowImpl that has getMap() method that returns an object that implements the Map interface and turns any call like view.map[‘attributeName’] or view.map.attributeName (these two are equivalent for Maps) into the appropriate getAttribute(‘attributeName’) call on the underlying Row instance.

Implementing a Generic RowReader

The alternative approach, that does not require us to generate the ViewRowImpl for every ViewObject, is using a generic RowReader. A Class that accepts a Row as input and returns the value of the requested attribute. I have quickly created such a generic set up, that allows declarative expressions like this one:

... text="Employees in the selected Department #{RowReader[bindings.DeptView1.currentRow].Dname}" 

to access any attribute value on any row object. The Row object is passed into the RowReader managed bean and then the desired attribute is indicated. Note that for attributes of type Number we have to specify the value property for proper display.

The required configuration for this generic RowReader is the following managed bean entry in the faces-config.xml file:

<managed-bean>
<managed-bean-name>RowReader</managed-bean-name>
<managed-bean-class>nl.amis.adf.model.RowReaderHandler</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>

And of course the RowReaderHandler and RowReader classes themselves:

package nl.amis.adf.model;

import java.util.Collection;
import java.util.Map;
import java.util.Set;

import oracle.jbo.Row;

public class RowReaderHandler implements Map {
public RowReaderHandler() {
}

public Object get(Object key) {
RowReader rr = new RowReader();
rr.setRow((Row)key);
return rr;
}
... remainder of Map implementation

}

package nl.amis.adf.model;

import java.util.Collection;
import java.util.Map;
import java.util.Set;

import oracle.jbo.Row;

public class RowReader implements Map {

private Row row;
public RowReader() {
}
/**
* @param key The Name of the Attribute whose value we want to see (key should be a String)
* @return The value of the attribute specified through the key in the row set through setRow()
*/
public Object get(Object key) {
return row.getAttribute((String)key);
}
public void setRow(Row row) {
this.row = row;
}

public Row getRow() {
return row;
}

... remainder of default Map implementation
}
 

Note how the RowReaderHandler implements the Map interface, get’s setup with the Row instance – through the call from the EL expression to the get method – and then instantiates the real RowHandler, that also happens to implement the Map interface. The RowHandler is ‘injected’ with the Row. Any call on that RowReader object will read the requested value from the Row. 

 

5 Comments

  1. sagarvt2002 January 9, 2012
  2. Shiva February 25, 2011
  3. Alexis February 5, 2010
  4. Asim Ghaffar SHAGHAB July 23, 2008
  5. Steve January 31, 2007