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.