Let me take you to, how to do dynamic pagination using rich:dataTable, rich:datascroller, org.ajax4jsf.model.SerializableDataModel. We will get into a step by step approach on implementing Lazy Pagination using JSF-Richfaces-SEAM.

How to do Step by Step approach!
Step 1:
Create a Class DynamicDataModel extending org.ajax4jsf.model.SerializableDataModel; with all overridden methods.
public class DynamicDataModel extends SerializableDataModel {
@Override
public void update() {
// TODO Auto-generated method stub
}
@Override
public Object getRowKey() {
// TODO Auto-generated method stub
return null;
}
@Override
public void setRowKey(Object key) {
// TODO Auto-generated method stub
}
@Override
public void walk(FacesContext context, DataVisitor visitor, Range range, Object argument) throws IOException {
// TODO Auto-generated method stub
}
@Override
public int getRowCount() {
// TODO Auto-generated method stub
return 0;
}
@Override
public Object getRowData() {
// TODO Auto-generated method stub
return null;
}
@Override
public int getRowIndex() {
// TODO Auto-generated method stub
return 0;
}
@Override
public Object getWrappedData() {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean isRowAvailable() {
// TODO Auto-generated method stub
return false;
}
@Override
public void setRowIndex(int rowIndex) {
// TODO Auto-generated method stub
}
@Override
public void setWrappedData(Object data) {
// TODO Auto-generated method stub
}
}
Step 2:
Declare below given local variables to manipulate the pagination in the class.
private Integer rowId; private Map wrappedData = new HashMap(); private List wrappedKeys = null; private Integer totalRows = 0; private Integer firstRow = 0; private Integer numberOfRows = 0;
Step 3:
And now we have to implement following methods to achieve dynamic loading of limited data required to display on the page.
@Override
public Object getRowKey() {
return rowId;
}
@Override
public void setRowKey(Object key) {
this.rowId = (Integer) key;
}
@Override
public int getRowCount() {
if (null == rowCount) {
return rowCount.intValue();
}
return 0;
}
@Override
public Object getRowData() {
if (null == rowId) {
return null;
}
return wrappedData.get(rowId);
}
public SerializableDataModel getSerializableModel(Range range) {
if (null != wrappedKeys) {
return this;
}
return null;
}
Step 4:
Ignore following methods since they are never invoked by framework. However you can make use of it on need basis.
@Override
public int getRowIndex() {
return 0;
}
@Override
public Object getWrappedData() {
throw new UnsupportedOperationException();
}
@Override
public boolean isRowAvailable() {
if (rowId == null) {
return false;
} else {
return dataProvider.hasItemByRowId(rowId);
}
}
@Override
public void setRowIndex(int rowIndex) {
// ignore
}
@Override
public void setWrappedData(Object data) {
throw new UnsupportedOperationException();
}
Step 5:
Now I’m gonna explain the method walk(), vital part of implementation.
public void walk(FacesContext context, DataVisitor visitor, Range range, Object argument) throws IOException {
// This is method we have to populate a data for DataTable
//Range parameter provides the firstRow value and no. of rows value. Extract those values to local variables
this.firstRow = ((SequenceRange) range).getFirstRow();
this.numberOfRows = ((SequenceRange) range).getRows();
//we can populate the data from Service Call/Web Service Call For eg. Data from database or Search results using Range values
//Define getItemsByrange() method to extract the required data by passing the range values
List sampleDataList = getItemsByrange(this.firstRow, this.numberOfRows.intValue());
// Now store the data to wrappedKeys & wrappedData components for the framework to make use of.
wrappedKeys = new ArrayList();
if (!sampleDataList.isEmpty()) {
for (SampleData item : sampleDataList) {
wrappedKeys.add(item.getId());
wrappedData.put(item.getId(), item);
visitor.process(context, item.getId(), argument);
}
}
}
Step 6:
We have completed Java part; let’s move on to JSF code snippet to invoke the Java class
<rich:panel>
<rich:datascroller for="sampleData" maxpages="10" id="dsTop" fastcontrols="hide" renderifsinglepage="false" rerender="dsBtm"></rich:datascroller>
<rich:datatable id="sampleData" rowclasses="greyBg, whiteBg" styleclass="tablesorter" value="#{dynamicDataModel}" var="item" rowkeyvar="row" rows="10" width="674" border="0" cellspacing="0" cellpadding="0">
<rich:column sortable="true" sortby="#{item.id}">
<f:facet styleclass="header" name="header">
<h:outputtext value="ID"> </h:outputtext>
</f:facet>
<h:outputtext value="#{item.id}"></h:outputtext>
</rich:column>
<rich:column sortable="true" sortby="#{item.firstName}">
<f:facet styleclass="header" name="header">
<h:outputtext value="First Name"></h:outputtext>
</f:facet>
<h:outputtext value="#{item.firstName}"></h:outputtext>
</rich:column>
<rich:column sortable="true" sortby="#{item.lastName}">
<f:facet styleclass="header" name="header">
<h:outputtext value="Last Name"></h:outputtext>
</f:facet>
<h:outputtext value="#{item.lastName}"></h:outputtext>
</rich:column>
</rich:datatable>
<rich:datascroller for="sampleData" maxpages="10" id="dsBtm" fastcontrols="hide" renderifsinglepage="false" rerender="dsTop"></rich:datascroller>
</rich:panel>
That’s all we have to do above steps to achieve dynamic data model pagination through Lazy Pagination using JSF-Richfaces-SEAM. This approach could minimize the weight on presentation layer loading the required data for the page rather loading all the data; that are yet to be displayed in forthcoming pages assuming the data extraction calls are not so expensive.
Downloads
Code files used in the article. Now all the Code Snippets and related files will be shared from GitHub Repo.
If you have any queries please leave a comment.
