PaginatingDataModel.java
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.el.Expression;
import javax.faces.context.FacesContext;
import org.ajax4jsf.model.DataVisitor;
import org.ajax4jsf.model.Range;
import org.ajax4jsf.model.SequenceRange;
import org.ajax4jsf.model.SerializableDataModel;
import org.richfaces.model.ExtendedFilterField;
import org.richfaces.model.FilterField;
import org.richfaces.model.Modifiable;
import org.richfaces.model.Ordering;
import org.richfaces.model.SortField2;
public abstract class PaginatingDataModel<T, U> extends SerializableDataModel implements Modifiable {
private static final long serialVersionUID = 2954923950179861809L;
protected U currentPk;
protected int rowIndex;
protected boolean descending = true;
protected String sortField = null;
protected HashMap<String,Object> filterMap = new HashMap<String,Object>();
protected boolean detached = false;
protected List<U> wrappedKeys = new ArrayList<U>();
protected Integer rowCount;
protected Map<U, T> wrappedData = new HashMap<U, T>();
/**
*
* @see org.ajax4jsf.model.ExtendedDataModel#getRowKey()
*/
@Override
public Object getRowKey() {
return currentPk;
}
/**
*
* @see org.ajax4jsf.model.ExtendedDataModel#setRowKey(java.lang.Object)
*/
@SuppressWarnings("unchecked")
@Override
public void setRowKey(final Object key) {
this.currentPk = (U) key;
}
/**
*
* @see org.ajax4jsf.model.SerializableDataModel#update()
*/
@Override
public void update() {
detached = false;
}
/**
*
* @see org.ajax4jsf.model.ExtendedDataModel#getSerializableModel(org.ajax4jsf.model.Range)
*/
@Override
public SerializableDataModel getSerializableModel(final Range range) {
if (wrappedKeys != null) {
detached = true;
return this;
}
return null;
}
/**
*
* @see javax.faces.model.DataModel#setRowIndex(int)
*/
@Override
public void setRowIndex(final int arg0) {
rowIndex = arg0;
}
/**
*
* @see javax.faces.model.DataModel#setWrappedData(java.lang.Object)
*/
@Override
public void setWrappedData(final Object data) {
throw new UnsupportedOperationException();
}
/**
*
* @see javax.faces.model.DataModel#getRowIndex()
*/
@Override
public int getRowIndex() {
return rowIndex;
}
/**
*
* @see javax.faces.model.DataModel#getWrappedData()
*/
@Override
public Object getWrappedData() {
throw new UnsupportedOperationException();
}
/**
*
* @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(final FacesContext context, final DataVisitor visitor, final Range range, final Object argument)
throws IOException {
final int firstRow = ((SequenceRange) range).getFirstRow();
final int numberOfRows = ((SequenceRange) range).getRows();
if (detached) {
for (final U key : wrappedKeys) {
setRowKey(key);
visitor.process(context, key, argument);
}
} else { // if not serialized, than we request data from data provider
wrappedKeys = new ArrayList<U>();
for (final T object : findObjects(firstRow, numberOfRows, sortField, filterMap, descending)) {
wrappedKeys.add(getId(object));
wrappedData.put(getId(object), object);
visitor.process(context, getId(object), argument);
}
}
}
/**
*
* @see javax.faces.model.DataModel#isRowAvailable()
*/
@Override
public boolean isRowAvailable() {
if (currentPk == null) {
return false;
}
if (wrappedKeys.contains(currentPk)) {
return true;
}
if (wrappedData.entrySet().contains(currentPk)) {
return true;
}
try {
if (getObjectById(currentPk) != null) {
return true;
}
} catch (final Exception e) {
}
return false;
}
/**
*
* @see javax.faces.model.DataModel#getRowData()
*/
@Override
public Object getRowData() {
if (currentPk == null) {
return null;
}
T object = wrappedData.get(currentPk);
if (object == null) {
object = getObjectById(currentPk);
wrappedData.put(currentPk, object);
}
return object;
}
/**
*
* @see javax.faces.model.DataModel#getRowCount()
*/
@Override
public int getRowCount() {
if (rowCount == null) {
rowCount = getNumRecords(filterMap).intValue();
}
return rowCount;
}
@Override
public void modify(List<FilterField> filterFields, List<SortField2> sortFields) {
filterMap.clear();
SortField2 sortField2 = null;
String expressionStr = null;
ExtendedFilterField extendedFilterField = null;
Expression expression = null;
String value = null;
if (sortFields != null && !sortFields.isEmpty()) {
sortField2 = sortFields.get(0);
expression = sortField2.getExpression();
expressionStr = expression.getExpressionString();
if (!expression.isLiteralText()) {
expressionStr = expressionStr.replaceAll("[#|$]{1}\\{.*?\\.", "").replaceAll("\\}", "");
}
this.sortField = expressionStr;
if (sortField2.getOrdering() == Ordering.DESCENDING) {
this.descending = true;
} else {
this.descending = false;
}
}
if (filterFields != null && !filterFields.isEmpty()) {
for (FilterField filterField : filterFields) {
if (filterField instanceof ExtendedFilterField) {
extendedFilterField = (ExtendedFilterField) filterField;
value = extendedFilterField.getFilterValue();
if (value != null && !value.equals("")) {
expression = extendedFilterField.getExpression();
expressionStr = expression.getExpressionString();
if (!expression.isLiteralText()) {
expressionStr = expressionStr.replaceAll("[#|$]{1}\\{.*?\\.", "").replaceAll("\\}", "");
}
filterMap.put(expressionStr, value);
}
}
}
}
}
/**
* @param object
*
* @return U
*/
public abstract U getId(T object);
/**
*
* @param firstRow
*
* @param numberOfRows
*
* @param sortField
*
* @param descending
*
* @return List<T>
*/
public abstract List<T> findObjects(int firstRow, int numberOfRows, String sortField, HashMap<String,Object> filterMap, boolean descending);
/**
*
* @param id
*
* @return T
*/
public abstract T getObjectById(U id);
/**
*
* @return Long
*/
public abstract Long getNumRecords(HashMap<String,Object> filterMap);
}
PersonPaginatingDataModel.java
import java.util.HashMap;
import java.util.List;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
import at.ooegkk.svnet.juhealth.entity.Person;
import at.ooegkk.svnet.juhealth.service.PersonService;
@Name("personPaginatingDataModel")
public class PersonPaginatingDataModel extends PaginatingDataModel<Person, Long> {
private static final long serialVersionUID = 1868068053701471139L;
@In(required = false)
private PersonService personService;
/**
* @see PaginatingDataModel#getId
*/
@Override
public Long getId(Person person) {
return person.getId();
}
/**
* @see PaginatingDataModel#findObjects
*/
@Override
public List<Person> findObjects(int firstRow, int maxResult, String sortField, HashMap<String,Object> filterMap, boolean descending) {
return personService.getRange(firstRow, maxResult, sortField, filterMap, descending);
}
/**
* @see PaginatingDataModel#getObjectById(java.lang.Object)
*/
@Override
public Person getObjectById(Long id) {
return personService.getPersonById(id);
}
/**
*
* @see PaginatingDataModel#getNumRecords
*/
@Override
public Long getNumRecords(HashMap<String,Object> filterMap) {
return personService.getCount(filterMap);
}
}
PersonService.java
import java.util.HashMap;
import java.util.List;
import javax.ejb.Remote;
import at.ooegkk.svnet.juhealth.entity.Person;
@Remote
public interface PersonService {
public List<Person> findAllPersons();
public void save(Person p);
public void merge(Person p);
public void remove(Person p);
public Person getPersonById(Long id);
public Long getCount(HashMap<String,Object> filterMap);
public List<Person> getRange(Integer firstRow, Integer maxResult, String sortField, HashMap<String,Object> filterMap, boolean descending);
}
PersonServiceImpl.java
import java.util.HashMap;
import java.util.List;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import at.ooegkk.svnet.juhealth.dao.GenericDAO;
import at.ooegkk.svnet.juhealth.dao.PersonDAO;
import at.ooegkk.svnet.juhealth.entity.Person;
import at.ooegkk.svnet.juhealth.service.PersonService;
@Stateless
@SuppressWarnings("unchecked")
public class PersonServiceImpl implements PersonService {
@EJB(name="svnet-juhealth-EAR/PersonDAOImpl/local")
private PersonDAO personDAOImpl;
public List<Person> findAllPersons() {
List<Person> allPersons = personDAOImpl.findAll(Person.class);
return allPersons;
}
public void save(Person person) {
personDAOImpl.persist(person);
}
public void merge(Person person) {
personDAOImpl.merge(person);
}
public void remove(Person person) {
personDAOImpl.remove(person);
}
public Person getPersonById(Long id) {
Person p = (Person) personDAOImpl.findById(Person.class, id);
return p;
}
public Long getCount(HashMap<String,Object> filterMap) {
Long count = personDAOImpl.getCount(Person.class, filterMap);
return count;
}
public List<Person> getRange(Integer firstRow, Integer maxResult, String sortField, HashMap<String,Object> filterMap, boolean descending) {
List<Person> list = null;
if (descending) {
list = personDAOImpl.findByFilter(Person.class, firstRow, maxResult, sortField, GenericDAO.SORT_ORDER.DESC, filterMap);
} else {
list = personDAOImpl.findByFilter(Person.class, firstRow, maxResult, sortField, GenericDAO.SORT_ORDER.ASC, filterMap);
}
return list;
}
}
GenericDAO.java
package at.ooegkk.svnet.juhealth.dao;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import javax.ejb.Local;
@SuppressWarnings("unchecked")
@Local
public interface GenericDAO {
public enum SORT_ORDER {
ASC, DESC
};
public Object findById(Class entityClass, long id);
public List findAll(Class entityClass);
public List findAll(Class entityClass, String orderByAttribute, SORT_ORDER sortOrder);
public List findAll(Class entityClass, int maxResult);
public List findAll(Class entityClass, int firstRow, int maxResult);
public List findAll(Class entityClass, int maxResult, String orderByAttribute, SORT_ORDER sortOrder);
public void persist(Object entity, boolean flushImmediate);
public void persist(Object entity);
public Object merge(Object entity, boolean flushImmediate);
public Object merge(Object entity);
public void remove(Object entity, boolean flushImmediate);
public void remove(Object entity);
public Set<String> exludeNames();
public Long getCount(Class entityClass);
public Long getCount(Class entityClass, HashMap<String,Object> filterMap);
public List findByFilter(Class entityClass, int firstRow, int maxResult, String orderByAttribute, SORT_ORDER sortOrder,
HashMap<String, Object> filterMap);
}
GenericDAOImpl.java
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import at.ooegkk.svnet.juhealth.dao.GenericDAO;
@SuppressWarnings("unchecked")
@Stateless
public class GenericDAOImpl implements GenericDAO {
@PersistenceContext(unitName="svnet-juhealth")
private EntityManager entityManager;
public EntityManager getEntityManager() {
return entityManager;
}
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
public Object findById(Class entityClass, long id) {
return getEntityManager().find(entityClass, id);
}
public List findAll(Class entityClass) {
return getEntityManager().createQuery(
"select e from " + entityClass.getName() + " e ")
.getResultList();
}
public List findAll(Class entityClass,
String orderByAttribute, SORT_ORDER sortOrder) {
String sortOrderString = "desc";
if (sortOrder == SORT_ORDER.ASC) {
sortOrderString = "asc";
}
return getEntityManager().createQuery(
"select e from " + entityClass.getName() + " e order by " +
orderByAttribute + " " + sortOrderString).getResultList();
}
public List findAll(Class entityClass, int maxResult) {
Query q = getEntityManager().createQuery(
"select e from " + entityClass.getName() + " e ");
if (maxResult > 0) {
q.setMaxResults(maxResult);
}
return q.getResultList();
}
public List findAll(Class entityClass, int firstRow, int maxResult) {
Query q = getEntityManager().createQuery(
"select e from " + entityClass.getName() + " e ");
if (firstRow > 0) {
q.setFirstResult(firstRow);
}
if (maxResult > 0) {
q.setMaxResults(maxResult);
}
return q.getResultList();
}
public List findAll(Class entityClass, int maxResult,
String orderByAttribute, SORT_ORDER sortOrder) {
String sortOrderString = "desc";
if (sortOrder == SORT_ORDER.ASC) {
sortOrderString = "asc";
}
Query q = getEntityManager().createQuery(
"select e from " + entityClass.getName() + " e order by "
+ orderByAttribute + " " + sortOrderString);
if (maxResult > 0) {
q.setMaxResults(maxResult);
}
return q.getResultList();
}
public void persist(Object entity, boolean flushImmediate) {
getEntityManager().persist(entity);
if (flushImmediate)
getEntityManager().flush();
}
public void persist(Object entity) {
this.persist(entity, false);
}
public Object merge(Object entity, boolean flushImmediate) {
Object obj = getEntityManager().merge(entity);
if (flushImmediate)
getEntityManager().flush();
return obj;
}
public Object merge(Object entity) {
return this.merge(entity, false);
}
public void remove(Object entity, boolean flushImmediate) {
getEntityManager().remove(getEntityManager().merge(entity));
if (flushImmediate)
getEntityManager().flush();
}
public void remove(Object entity) {
this.remove(entity, false);
}
public Set<String> exludeNames() {
return new HashSet<String>();
}
public Long getCount(Class entityClass) {
Query q = getEntityManager().createQuery(
"select count(e) from " + entityClass.getName() + " e ");
return (Long) q.getSingleResult();
}
public Long getCount(Class entityClass, HashMap<String,Object> filterMap) {
StringBuffer query = new StringBuffer();
query.append("select count(e) from " + entityClass.getName() + " e");
// where clause
query.append(this.getWhereClause(filterMap));
Query q = getEntityManager().createQuery(query.toString());
// parameter
q = this.getParameteredQuery(q, filterMap);
return (Long) q.getSingleResult();
}
public List findByFilter(Class entityClass, int firstRow, int maxResult,
String orderByAttribute, SORT_ORDER sortOrder, HashMap<String,Object> filterMap) {
StringBuffer query = new StringBuffer();
query.append("SELECT e FROM " + entityClass.getName() + " e");
// sort order
String sortOrderString = "desc";
if (sortOrder == SORT_ORDER.ASC) {
sortOrderString = "asc";
}
// where clause
query.append(this.getWhereClause(filterMap));
// order by
if (orderByAttribute != null) {
query.append(" ORDER BY " + orderByAttribute + " " + sortOrderString);
}
Query q = getEntityManager().createQuery(query.toString());
// parameter
q = this.getParameteredQuery(q, filterMap);
if (firstRow > 0) {
q.setFirstResult(firstRow);
}
if (maxResult > 0) {
q.setMaxResults(maxResult);
}
return q.getResultList();
}
private String getWhereClause(HashMap<String,Object> filterMap) {
StringBuffer query = new StringBuffer();
if (filterMap != null && !filterMap.isEmpty()) {
query.append(" WHERE");
boolean first = true;
for (String column : filterMap.keySet()) {
if (first) {
first = false;
} else {
query.append(" AND");
}
if (filterMap.get(column) instanceof String) {
query.append(" UPPER(e." + column + ") LIKE :" + column);
} else {
query.append(" e." + column + " = :" + column);
}
}
}
return query.toString();
}
private Query getParameteredQuery(Query q, HashMap<String,Object> filterMap) {
if (filterMap != null && !filterMap.isEmpty()) {
for (String column : filterMap.keySet()) {
if (filterMap.get(column) instanceof String) {
String value = (String) filterMap.get(column);
q.setParameter(column, value.toUpperCase() + "%");
} else {
q.setParameter(column, filterMap.get(column));
}
}
}
return q;
}
}
PersonDAO.java
import javax.ejb.Local;
@Local
public interface PersonDAO extends GenericDAO {
}
PersonDAOImpl.java
import javax.ejb.Stateless;
import at.ooegkk.svnet.juhealth.dao.PersonDAO;
@Stateless
public class PersonDAOImpl extends GenericDAOImpl implements PersonDAO {
}
AbstractEntity.java
import java.io.Serializable;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
@MappedSuperclass
public class AbstractEntity implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private Long id;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}
Person.java
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
import org.hibernate.validator.Length;
import org.hibernate.validator.NotNull;
import org.jboss.seam.annotations.Name;
import at.ooegkk.intranet.example.validator.VSNR;
@Name("person")
@Entity
@Table
@Cache(usage=CacheConcurrencyStrategy.READ_WRITE)
public class Person extends AbstractEntity implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private String vorname;
private String nachname;
private String vsnr;
private Date geburtsdatum;
private Address adresse = new Address();
@Column
@NotNull(message="#{messages['field.required']}")
public String getVorname() {
return vorname;
}
public void setVorname(String vorname) {
this.vorname = vorname;
}
@Column
public String getNachname() {
return nachname;
}
public void setNachname(String nachname) {
this.nachname = nachname;
}
@Column
@NotNull
@Length(max=10,min=10)
public String getVsnr() {
return vsnr;
}
public void setVsnr(String vsnr) {
this.vsnr = vsnr;
}
@OneToOne(targetEntity=Address.class)
@Cascade(value=CascadeType.ALL)
public Address getAdresse() {
return adresse;
}
public void setAdresse(Address adresse) {
this.adresse = adresse;
}
@Column
public Date getGeburtsdatum() {
return geburtsdatum;
}
public void setGeburtsdatum(Date geburtsdatum) {
this.geburtsdatum = geburtsdatum;
}
}
Address.java
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import org.hibernate.validator.NotNull;
import org.jboss.seam.annotations.Name;
@Entity
@Table
@Name("adresse")
public class Address extends AbstractEntity implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private Integer plz;
private String ort;
private String strasse;
@Column
public Integer getPlz() {
return plz;
}
public void setPlz(Integer plz) {
this.plz = plz;
}
@Column
public String getOrt() {
return ort;
}
public void setOrt(String ort) {
this.ort = ort;
}
@Column
@NotNull
public String getStrasse() {
return strasse;
}
public void setStrasse(String strasse) {
this.strasse = strasse;
}
}
index.xhtml
<rich:dataTable value="#{personPaginatingDataModel}" var="person" rows="3" reRender="scroller" id="simpletable" width="100%" rowClasses="firstrow,secondrow"<
<f:facet name="header"<
<h:outputText value="Personen"/<
</f:facet<
<rich:column width="10%"<
<s:link action="#{personManager.personEdit}"<
<f:param name="personId" value="#{person.id}"/<
<img src="/img/icon_bearbeiten.gif" alt="Bearbeiten"/<
</s:link<
</rich:column<
<rich:column width="18%"<
<f:facet name="header"<
<h:outputText value="SVNR"/<
</f:facet<
<h:outputText value="#{person.vsnr}"/<
</rich:column<
<rich:column sortBy="#{person.vorname}" filterBy="#{person.vorname}" filterEvent="onkeyup" filterValue="#{personManager.currentVornameFilterValue}" width="18%"<
<f:facet name="header"<
<h:outputText value="Vorname"/<
</f:facet<
<h:outputText value="#{person.vorname}"/<
</rich:column<
<rich:column filterBy="#{person.nachname}" filterEvent="onkeyup" filterValue="#{personManager.currentNachnameFilterValue}" width="18%"<
<f:facet name="header"<
<h:outputText value="Nachname"/<
</f:facet<
<h:outputText value="#{person.nachname}"/<
</rich:column<
<rich:column width="18%"<
<f:facet name="header"<
<h:outputText value="Strasse"/<
</f:facet<
<h:outputText value="#{person.adresse.strasse}"/<
</rich:column<
<rich:column width="8%"<
<f:facet name="header"<
<h:outputText value="PLZ"/<
</f:facet<
<h:outputText value="#{person.adresse.plz}"/<
</rich:column<
<rich:column width="10%"<
<f:facet name="header"<
<h:outputText value="Ort"/<
</f:facet<
<h:outputText value="#{person.adresse.ort}"/<
</rich:column<
</rich:dataTable<
<rich:datascroller id="scroller" renderIfSinglePage="false" for="simpletable"<</rich:datascroller<
Edit at 2012/09/26: The reason that some readers were asking for the source code of the PersonManager, I edited this post. Because I have improved the PersonManager since the creation of the first post, I inserted an older version from the repository. Hopefully it is compatible with the other code.
PersonManager
import java.util.List;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Begin;
import org.jboss.seam.annotations.End;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Out;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.web.RequestParameter;
import at.ooegkk.svnet.juhealth.datamodel.PersonPaginatingDataModel;
import at.ooegkk.svnet.juhealth.entity.Person;
import at.ooegkk.svnet.juhealth.service.PersonService;
@Name("personManager")
@Scope(ScopeType.SESSION)
public class PersonManager {
@In(required = false)
private PersonService personService;
@In(create = true)
@Out(required = false)
public Person person;
@Out(required = false)
public Person searchPerson = new Person();
@RequestParameter
public Long personId;
public String currentVornameFilterValue;
public String currentNachnameFilterValue;
@In(create = true)
public PersonPaginatingDataModel personPaginatingDataModel;
public PersonManager() {
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
public Person getSearchPerson() {
return searchPerson;
}
public void setSearchPerson(Person searchPerson) {
this.searchPerson = searchPerson;
}
public PersonPaginatingDataModel getPersonPaginatingDataModel() {
return personPaginatingDataModel;
}
public void setPersonPaginatingDataModel(PersonPaginatingDataModel personPaginatingDataModel) {
this.personPaginatingDataModel = personPaginatingDataModel;
}
public String personenList() {
return "personenList";
}
public String personAdd() {
return "personAdd";
}
@Begin(join = true)
@End
public String personSave() throws Exception {
try {
if (person.getId() == null) {
this.personService.save(person);
} else {
this.personService.merge(person);
}
return "personSave";
} catch (Exception e) {
throw e;
}
}
public String personReset() throws Exception {
try {
person = new Person();
return "personReset";
} catch (Exception e) {
throw e;
}
}
public String personEdit() throws Exception {
try {
person = this.personService.getPersonById(personId);
return "personEdit";
} catch (Exception e) {
throw e;
}
}
public String personenSearch() throws Exception {
try {
return "personenSearch";
} catch (Exception e) {
throw e;
}
}
public List getPersonen() throws Exception {
try {
return this.personService.findAllPersons();
} catch (Exception e) {
throw e;
}
}
public String getCurrentVornameFilterValue() {
return currentVornameFilterValue;
}
public void setCurrentVornameFilterValue(String currentVornameFilterValue) {
this.currentVornameFilterValue = currentVornameFilterValue;
}
public String getCurrentNachnameFilterValue() {
return currentNachnameFilterValue;
}
public void setCurrentNachnameFilterValue(String currentNachnameFilterValue) {
this.currentNachnameFilterValue = currentNachnameFilterValue;
}
}