Home > Data Model, RichFaces > Implementing richfaces extended data model classes

Implementing richfaces extended data model classes


RichFaces data driven components (rich:dataTable , rich:dataGrid etc.) can be used in more complicated scenarios unlike standard DataTable and DataModel class. To get the new supports one needs to implement his own DataModel that extends one of ExtendedDataModel classes. But it’s not efficient every time implementing the class when needs. So here I write my own solution.

Implementation

I extend org.ajax4jsf.model.SerializableDataModel class as usual. But the tricks lie in overridden walk method. A general fetch list of ExtendedFetchList is used to access data instead of a specific fetch list. ExtendedFetchList interface declares all the necessary methods for dynamic data accessing. See the following codes and usage example.

ExtendedListDataModel:

public class ExtendedListDataModel extends SerializableDataModel {
private boolean detached = false;
private BigDecimal currentPk;
private Map wrappedData = new HashMap();
private List wrappedKeys = null;
private ExtendedFetchList fetchList = null;
private int rowIndex;
private static final long serialVersionUID = 1L;
/* (non-Javadoc)
* @see org.ajax4jsf.model.SerializableDataModel#update()
*/
@Override
public void update() {
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see org.ajax4jsf.model.ExtendedDataModel#getRowKey()
*/
@Override
public Object getRowKey() {
// TODO Auto-generated method stub
return currentPk;
}
/* (non-Javadoc)
* @see org.ajax4jsf.model.ExtendedDataModel#setRowKey(java.lang.Object)
*/
@Override
public void setRowKey(Object key) {
// TODO Auto-generated method stub
this.currentPk = (BigDecimal)key;
}
/* (non-Javadoc)
* @see org.ajax4jsf.model.ExtendedDataModel#walk(javax.faces.context.FacesContext, org.ajax4jsf.model.DataVisitor, org.ajax4jsf.model.Range, java.lang.Object)
*/
@Override
public void walk(FacesContext context, DataVisitor visitor, Range range, Object argument) throws IOException {
int firstRow = ((SequenceRange)range).getFirstRow();
int numberOfRows = ((SequenceRange)range).getRows();
if (detached) { // Is this serialized model
// Here we just ignore current Rage and use whatever data was saved in serialized model.
// Such approach uses much more getByPk() operations, instead of just one request by range.
// Concrete case may be different from that, so you can just load data from data provider by range.
// We are using wrappedKeys list only to preserve actual order of items.
for (BigDecimal key:wrappedKeys) {
setRowKey(key);
visitor.process(context, key, argument);
}
} else { // if not serialized, than we request data from data provider
wrappedKeys = new ArrayList();
for (Object obj:fetchList.fetchList(firstRow, numberOfRows)) {
wrappedKeys.add(fetchList.getPk(obj));
wrappedData.put(fetchList.getPk(obj), obj);
visitor.process(context, fetchList.getPk(obj), argument);
}
}
}
/* (non-Javadoc)
* @see javax.faces.model.DataModel#getRowCount()
*/
@Override
public int getRowCount() {
// TODO Auto-generated method stub
//return fetchList.getListSize();
return fetchList.getMaxListSize();
}
/* (non-Javadoc)
* @see javax.faces.model.DataModel#getRowData()
*/
@Override
public Object getRowData() {
// TODO Auto-generated method stub
if (currentPk == null) {
return null;
} else {
Object ret = wrappedData.get(currentPk);
return ret;
}
}
/* (non-Javadoc)
* @see javax.faces.model.DataModel#getRowIndex()
*/
@Override
public int getRowIndex() {
// TODO Auto-generated method stub
//throw new UnsupportedOperationException();
return rowIndex;
}
/* (non-Javadoc)
* @see javax.faces.model.DataModel#getWrappedData()
*/
@Override
public Object getWrappedData() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException();
}
/* (non-Javadoc)
* @see javax.faces.model.DataModel#isRowAvailable()
*/
@Override
public boolean isRowAvailable() {
// TODO Auto-generated method stub
if (currentPk == null) {
return false;
} else {
return wrappedData.containsKey(currentPk);
}
}
/* (non-Javadoc)
* @see javax.faces.model.DataModel#setRowIndex(int)
*/
@Override
public void setRowIndex(int arg0) {
// TODO Auto-generated method stub
//throw new UnsupportedOperationException();
rowIndex = arg0;
return;
}
/* (non-Javadoc)
* @see javax.faces.model.DataModel#setWrappedData(java.lang.Object)
*/
@Override
public void setWrappedData(Object arg0) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException();
}
public SerializableDataModel getSerializableModel(Range range) {
if (wrappedKeys != null) {
detached = true;
// Some activity to detach persistent data from wrappedData map may be taken here.
// In that specific case we are doing nothing.
return this;
} else {
return null;
}
}
/**
* @return the fetchList
*/
public ExtendedFetchList getFetchList() {
return fetchList;
}
/**
* @param fetchList the fetchList to set
*/
public void setFetchList(ExtendedFetchList fetchList) {
this.fetchList = fetchList;
}
}

ExtendedFetchList

public interface ExtendedFetchList {
public List fetchList(int startRow, int size);
public BigDecimal getPk(Object obj);
public void update();
public int getListSize();
public int getMaxListSize();
}

Usage: An Example

AnExampleListModel:

public class AnExampleListModel implements Serializable {
private ExtendedListDataModel exampleList = new ExtendedListDataModel();
private ExtendedFetchList fetchList;
private static final long serialVersionUID = 102136548978979L;
/**
* @return the exampleList
*/
public ExtendedListDataModel getExampleList() {
return exampleList;
}
/**
* @param exampleList the exampleList to set
*/
public void setExampleList(ExtendedListDataModel exampleList) {
this.exampleList = exampleList;
}
/**
* @return the fetchList
*/
public ExtendedFetchList getFetchList() {
return fetchList;
}
/**
* @param fetchList the fetchList to set
*/
public void setFetchList(ExtendedFetchList fetchList) {
this.fetchList = fetchList;
exampleList.setFetchList(fetchList);
}
}

AnExampleFetchList:

public class AnExampleFetchList implements ExtendedFetchList, Serializable {
private static final long serialVersionUID = 1L;
private int listSize;
private int maxListSize;
public List fetchList(int startRow, int size) {
List list = new Vector();
//call some method here to populate the list
//For example
RangeQueryResult rqr = foo.getBars(startRow, size);
list = rqs.getResultList();
setListSize(list.size());
setMaxListSize(rqr.getMaxResult());
return list;
}
@SuppressWarnings("unchecked")
public BigDecimal getPk(Object obj) {
Map columns = (Map) obj;
return new BigDecimal(columns.get("id").toString());
}
public void update() {}
public int getListSize(){
return listSize;
}
public int getMaxListSize(){return maxListSize;}
/**
* @param listSize the listSize to set
*/
public void setListSize(int listSize) {
this.listSize = listSize;
}
/**
* @param maxListSize the maxListSize to set
*/
public void setMaxListSize(int maxListSize) {
this.maxListSize = maxListSize;
}
}

Bean Definitions:

<managed-bean>
<managed-bean-name>exampleListModel</managed-bean-name>
<managed-bean-class>
com.mycompany.web.model.AnExampleListModel
</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
<managed-property>
<property-name>fetchList</property-name>
<property-class>
com.iecb.web.model.AnExampleFetchList
</property-class>
<value>#{exampleFetchList}</value>
</managed-property>
</managed-bean>
<managed-bean>
<managed-bean-name>exampleFetchList</managed-bean-name>
<managed-bean-class>
com.iecb.web.model.AnExampleFetchList
</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>

Example Template:
<h:panelGrid id="exampleContainer" columns="1">
<rich:dataTable id="exampleListDT" value="#{exampleListModel.exampleList}" var="item" rows="25" style="width:100%">
<h:column>
<f:facet name="header">
<h:outputText value="Column1" />
</f:facet>
<h:outputText value="#{item['column1']}" />
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Column2" />
</f:facet>
<h:outputText value="#{item['column2']}" />
</h:column>
</rich:dataTable>
<rich:spacer height="5" />
<rich:datascroller align="left" for="exampleListDT" maxPages="10" ajaxSingle="false"/>
</h:panelGrid>

Advertisements
  1. July 9, 2010 at 10:40 pm

    Can you suggest the format of what I show add here for sample rows instead of RangeQueryResult:

    //call some method here to populate the list
    RangeQueryResult rqr = foo.getBars(startRow, size);
    list = rqs.getResultList();

    I tried adding a BigDecimal object with:

    list.add (new BigDecimal(1.23));

    I get an exception here at this line in the getPk() method:

    Map columns = (Map) obj;

    The exception is

    java.lang.ClassCastException: java.math.BigDecimal

  2. thiagu
    March 13, 2010 at 5:26 am

    i don’t have any issue with implementing extended data model.
    but i have one more requirement with extended data model is how to select multiple rows from the data table.
    for that i put the h:booleanSelection component in the data table and i make it ajaxSingle property for rich:dataScroller as false.(to submit the checkbox status to action class when i navigating across mutiple pages by using datascroller ).
    now i am facing the problem with extended data models walk method.
    this method getting invoked 4 times instead of once.
    so how to implement the multiple row selection in the extended data model.

  3. Kristein
    July 27, 2009 at 8:59 pm

    could you please provide with a complete solution.
    It’s really helpful for others.

    thanks,
    Kristein

  4. December 27, 2008 at 12:03 am

    yes please !! I need a example with hibernate, i have a table with 50,000 rows, but it’s very slow in the traditional form with (rich:datascroller).

    Do you have any solution?

  5. wandrey
    December 1, 2008 at 12:36 am

    Great
    Can your example work with richfaces version 3,2.2 and 3.3 ?
    Can you share your update solution?

  6. Rafael
    September 12, 2008 at 3:22 pm

    Thanks for your article.

  7. September 11, 2008 at 7:41 am

    Hi, Had a doubt, in the above example

    what these does, no code given for it.
    RangeQueryResult rqr = foo.getBars(startRow, size);
    list = rqs.getResultList();

    Instead of these, i written my own impl class which returns a Arraylist.
    But in JSP, it is throwing classcastexception. Need help on this.

    Thanks,
    Vimal.

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: