[jboss-user] [JBoss Seam] - Here is a Richfaces Ajax Datascroler and Seam Example

supernovasoftware.com do-not-reply at jboss.com
Fri Dec 14 11:26:02 EST 2007


I use the following to view large tables where fetching the all the results is not feasible.  It has about 1 million rows.

It does assume that you object implements the interface Idable  shown next.

  | 
  | import java.io.IOException;
  | import java.io.Serializable;
  | import java.util.ArrayList;
  | import java.util.HashMap;
  | import java.util.List;
  | import java.util.Map;
  | 
  | import javax.faces.context.FacesContext;
  | 
  | import org.ajax4jsf.model.DataVisitor;
  | import org.ajax4jsf.model.ExtendedDataModel;
  | import org.ajax4jsf.model.Range;
  | import org.ajax4jsf.model.SequenceRange;
  | import org.jboss.seam.ScopeType;
  | import org.jboss.seam.annotations.Logger;
  | import org.jboss.seam.annotations.Out;
  | import org.jboss.seam.log.Log;
  | 
  | import my.package.Idable;
  | 
  | public abstract class BaseExtendedDataModel<T,ID extends Serializable> extends ExtendedDataModel implements  BaseExtendedDataModelDAO<T, ID>{
  | 
  | 	private @Logger Log log;
  | 	
  | 	@Out(scope=ScopeType.CONVERSATION, required=false)
  | 	public List<T> listRow;
  | 	
  | 	private ID currentId;
  | 	private Map<ID, T> wrappedData = new HashMap<ID, T>();
  | 	private List<ID> wrappedKeys;
  | 	private Long rowCount; // better to buffer row count locally
  | 	
  | 	public abstract Long getCount();
  | 	public abstract List<T> getList(Integer firstRow, Integer maxResults);
  | 	public abstract T findById(ID id);
  | 	
  | 	public void wrap(FacesContext context, DataVisitor visitor, Range range, Object argument, List<T> list) throws IOException
  | 	{
  | 		wrappedKeys = new ArrayList<ID>();
  | 		wrappedData = new HashMap<ID, T>();
  | 		for (T row : list)
  | 		{
  | 			Idable idable = (Idable) row;
  | 			ID id = (ID) idable.getId();
  | 			wrappedKeys.add(id);
  | 			wrappedData.put(id, row);
  | 			visitor.process(context, id, argument);
  | 		}		
  | 	}	
  | 	
  | 	public boolean hasById(ID id) 
  | 	{
  | 		for (T row : listRow) 
  | 		{
  | 			Idable idable = (Idable) row;
  | 			Long rowId = (Long) idable.getId();
  | 			if (rowId.equals(id))
  | 			{
  | 				return true;
  | 			}
  | 		}
  | 		return false;		
  | 	}
  | 	
  | 	@Override
  | 	public void walk(FacesContext context, DataVisitor visitor, Range range, Object argument) throws IOException
  | 	{		
  | 		int firstRow = ((SequenceRange) range).getFirstRow();
  | 		int maxResults = ((SequenceRange) range).getRows();
  | 		wrap(context, visitor, range, argument, getList(firstRow, maxResults));
  | 	}
  | 	
  |     /*
  | 	 * This method normally called by Visitor before request Data Row.
  | 	 */ 
  | 	@Override
  | 	public void setRowKey(Object key) 
  | 	{
  | 		this.currentId = (ID) key;
  | 	}
  | 	
  | 	@Override
  | 	public int getRowCount() 
  | 	{
  | 	  if(rowCount == null) 
  | 	    return (rowCount = this.getCount()).intValue();  
  | 	  else 
  |         return rowCount.intValue();
  | 	}
  | 	
  | 	@Override
  | 	public boolean isRowAvailable() 
  | 	{
  | 		if (currentId == null) {
  | 			return false;
  | 		} else {
  | 			return hasById(currentId);
  | 		}
  | 	}
  | 	
  | 	/**
  | 	 * This is main way to obtain data row. It is intensively used by framework.
  | 	 * We strongly recommend use of local cache in that method.
  | 	 */
  | 	@Override
  | 	public Object getRowData() {
  | 		if (currentId == null) {
  | 			return null;
  | 		} else {
  | 			T ret = wrappedData.get(currentId);
  | 			if (ret == null) {
  | 				ret = this.findById(currentId);
  | 				wrappedData.put(currentId, ret);
  | 				return ret;
  | 			} else {
  | 				return ret;
  | 			}
  | 		}
  | 	}
  | 	
  | 	/**
  | 	 * Unused rudiment from old JSF staff. 
  | 	 */
  | 	@Override public Object getWrappedData() { throw new UnsupportedOperationException(); }
  | 	@Override public int getRowIndex() { throw new UnsupportedOperationException();	}
  | 	@Override public void setRowIndex(int rowIndex) { throw new UnsupportedOperationException(); }
  | 	@Override public void setWrappedData(Object data) { throw new UnsupportedOperationException(); }
  | 	
  | 	/**
  | 	 * Unused update data. 
  | 	 */
  | //	@Override public void update() { throw new UnsupportedOperationException(); }
  | 
  | 	/**
  | 	 * TODO if this is never called by the framework why is it necessary.
  | 	 */ 
  | 	@Override public Object getRowKey() { if (true) throw new UnsupportedOperationException(); return currentId; }
  | 
  | }
  | 
  | public interface BaseExtendedDataModelDAO<T, ID> {
  |   | 
  |   | }
  | 
  | 
Idable interface

  | public interface Idable
  | {
  | 	public Long getId();
  | }
  | 

I extend the base class as shown below.




  | import java.util.List;
  | 
  | import org.jboss.seam.annotations.In;
  | import org.jboss.seam.annotations.Name;
  | 
  | import mypackage.general.access.Access;
  | 
  | @Name("accessExtendedDataModel")
  | public class AccessExtendedDataModel extends BaseExtendedDataModel<Access, Long>  
  | {
  | 	@In(create=true) AccessDAO accessDAO;
  | 	
  | 	@Override
  | 	public Long getCount() 
  | 	{		
  | 	  return accessDAO.getCount();
  | 	}
  | 	
  | 	@Override
  | 	public Access findById(Long id) 
  | 	{		
  | 	  return accessDAO.findById(id);
  | 	}
  | 	
  | 	@Override
  | 	public List<Access> getList(Integer firstRow, Integer maxResults)
  | 	{
  | 		return listRow = accessDAO.getRange(firstRow, maxResults);
  | 	}
  | 

Then in the facelets page


  |   <a4j:form>
  |     <rich:datascroller for="accessList" />
  |     <rich:spacer height="10" />
  |     <rich:dataTable id="accessList"
  |                  value="#{accessExtendedDataModel}"
  |                    var="accessL"
  |             styleClass="f_table"
  |             rowClasses="tr0,tr1"
  |                   rows="30">
  |       <rich:column id="id">
  |         <f:facet name="header">id</f:facet>
  |         <h:outputText value="#{accessL.id}" />
  |       </rich:column>
  |       <rich:column id="User">
  |         <f:facet name="header">User</f:facet>
  |         <h:outputText value="#{accessL.usr.usr}" />
  |       </rich:column>
  |     </rich:dataTable>
  |   </a4j:form>
  | 

The scroller is now connected to the datatable.  This is a first pass and was adapted for an example in the Richfaces cvs I took a while back.

The paging is all done with Ajax and only 30 objects are loaded at a time.

Any suggestions for improvement are most welcome.


View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4112998#4112998

Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4112998



More information about the jboss-user mailing list