Help

Overview

I believe that this probably one of the most expected articles to come. It will touch the RichFaces iteration component in-depth, covering advanced models which we are using under the hood. Actually real enterprise application using huge data sets, applies paging with lazy data loading, uses sorting, filtering, selection and the other features which makes then application really rich and interactive. So in most cases you could not rely on simple lists or maps with data wrapped using default models. And in order to achieve the best RichFaces tables experience with a good performance and scalability you need to understand the base principles of our models.

Models sample

At first I would like to introduce new sample available on our live demo – Arrangeable Model Sample. It works using Hibernate Entity Manager and all the paging/sorting/filtering operations really performed at DB level instead of performing in wrapped model.

In that article I will guide you through the base points which you should look in that sample in order to get main ideas and be able to work on your own models.

Why do we need the models

Let's start from a good question – why RichFaces introduces custom models having JSF javax.faces.model.DataModel contract already. And the reason is pretty simple. In difference with JSF 2 implementation which is supposed just to provide basic stuff RichFaces introduces new rich components and adds new features on top of them. Here is just overview:

  • Trees components family. With support of swing-based data models and RichFaces custom data models. With additional providers which allows to create data model declaratively from any custom non-hierarchical model. With selection feature plugged and available using different modes (Ajax, client, server)
  • Tables components family. RichFaces unifies sorting/filtering/paging features among two rich tables. It adds the ability of master-detail layouts creation in rich:dataTable with the built-in feature of collapse/expand details subtables. It adds Ajax lazy loading of the data on vertical scroll and selection with rich:extendedDataTable. And so on..

Of course all that stuff requires good model base. And in order to standardize the API between different components providing unified contract to the RichFaces developers we designed our models.

ExtendedDataModel Overview

From the beginning let me introduce our models principles and then later we will see how them are implemented in the showcase demo.

ExtendedDataModel

is a base model abstract class which provides the contract for all the other models particular implementations. Let’s see closer to that class:

public abstract class ExtendedDataModel<E> extends DataModel<E> {

    public abstract void setRowKey(Object key);

    public abstract Object getRowKey();

    public abstract void walk(FacesContext context, DataVisitor visitor, Range range, Object argument);

}

Well, we seeing new entity introduced there. And it’s rowKey. Let’s see the goal of that entity. Working with complex data structures (like trees) and using advanced UI component features like filtering/sorting/paging/selection in tables we need to have a simple way to identify the object in the model. And just rowIndex’es doesn’t play nice enough as requires additional complex look-up mechanisms (to identify db object according to index in wrapped model) to do that. And with the rowKey you could just use the same id which you are using at db level.

Besides you see walk() method introduced there. RichFaces iteration components uses visitor pattern while working with model. So that method should perform model iteration and call the visitor passed as a parameter in order to handle every object in the model.

ExtendedDataModel implementations

  • SequenceDataModel – default implementation of the ExtendedDataModel for the tables. Used when filtering and sorting not used by the component.
  • ArrangeableModel – implementation of the ExtendedDataModel which implements Arrangeable interface additionally which are used to add sorting and filtering support.
  • TreeSequenceKeyModel abstract model and all the models which extends it used by the tree component family. That model is out of scope for that article.

Sample Code

At first I would like to say that will not describe all the code used in the sample. You could easily check it at showcase live or obtain from SVN repository and explore in your favorite IDE. Besides the fact that it will be boring and will make article really huge I also want to say that the goal of that write-up – to guide you in the right direction while reviewing RichFaces data models usage principles.

And overview of that sample functionality:

  • Obtaining the list of Person object s from the db according to given filtering and sorting rules
  • Displaying objects using the rich:dataTable
  • Addition of the controls which control sorting and filtering
  • Addition of the rich:dataScroller which allows breaking the data loading from db to the pages.

Sample Code – Base Person entity

That would be self-explanatory I believe. We just using simple and frequently used classes to define Person object.

@Entity
public class Person {
    
    private String name;
    private String surname;
    private String email;
    @Id
    @GeneratedValue
    private Long id;
//getters and setters
}

Sample Code – Generic Model

Now let’s look closer to the model code.

JPADataModel

–is a generic model which supposed to provide unified approach of working with data for all implementers. It’s parameterized with the class which should be defined to work with particular entity classes in models which will implement it. And besides it passed with the EntityManager in order the implementer classes to be responsible for particular EntityManager lookup.

Also from the beginning you should note abstract getId(T t) method which should be also implemented in the model which implements that abstract model. It should return the id of the particular entity which will be used as rowKey in that model.

Now let’s review two most important methods there. And let’s look to arrange() method from the beginning. It probably too simple to have it listed but any way:

public void arrange(FacesContext context, ArrangeableState state) {
    arrangeableState = state;
}

Just wanted to give some simple explanation of why we perform just simple storing of the passed state in the model property without any further processing. If you will look or already looked to RichFaces sources you will see that default ArrangeableModel implementation of that method performs actual sorting and filtering. But that’s done because our default model works with wrapped model (e.g. simple list or map passed as rich:dataTable value). But in our case we will load the data from db according to current data table page and apply sorting and filtering using db queries also. So we just need to store all the information passed from component in ArrangeableState object for future usage in walk().

Now let’s look to walk() method:

    @Override
    public void walk(FacesContext context, DataVisitor visitor, Range range, Object argument) {
        CriteriaQuery<T> criteriaQuery = createSelectCriteriaQuery();
        TypedQuery<T> query = entityManager.createQuery(criteriaQuery);
        
        SequenceRange sequenceRange = (SequenceRange) range;
        if (sequenceRange.getFirstRow() >= 0 && sequenceRange.getRows() > 0) 
	{
            query.setFirstResult(sequenceRange.getFirstRow());
            query.setMaxResults(sequenceRange.getRows());
        }
        
        List<T> data = query.getResultList();
        for (T t : data) {
            visitor.process(context, getId(t), argument);
        }
    }

The component calls that method a few times during lifecycle and expects it to iterate over the model calling the DataVisitor which will process every object (e.g. encode row for the object at render phase).

Besides visitor, table component passes the Range object there which contains information about from which row the table wants get the data (defined using first attribute or set by rich:dataScroller while switching pages) and the number of rows to fetch (defined using rows attribute). So all we are doing here – just creating query with given sort, filtering and range parameters, loading data from db to the List of entities and finally iterate over that list passing every object to DataVisitor for processing.. You probably will be interested in createSelectCriteriaQuery() method as it performs actual applying of sort and filter parameters. But actually I would like to leave it just to you because JPA queries creation question really out of scope of that article and well explained already at more specific resources.

Besides you may be interested to look into getRowCount() method:

    @Override
    public int getRowCount() {
        CriteriaQuery<Long> criteriaQuery = createCountCriteriaQuery();
        return entityManager.createQuery(
	    criteriaQuery).getSingleResult().intValue();
    }

So there we’re applying sorting and filtering creating the criteria in order to return the rowCount for current component state.

Sample Code – Specific Model Class

The implementation of our generic model placed in PersonBean and defined with the next code:

@ManagedBean
@SessionScoped
public class PersonBean implements Serializable {
    //...
    private static final class PersonDataModel extends JPADataModel<Person> {
        private PersonDataModel(EntityManager entityManager) {
            super(entityManager, Person.class);
        }
        @Override
        protected Object getId(Person t) {
            return t.getId();
        }
    }
    //...
    private EntityManager lookupEntityManager() {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        PersistenceService persistenceService = 
	    facesContext.getApplication().
	    evaluateExpressionGet(facesContext, "#{persistenceService}", 
      PersistenceService.class);
        return persistenceService.getEntityManager();
    }

    public Object getDataModel() {
        return new PersonDataModel(lookupEntityManager());
    }
    //...
}

So actually all we are doing there - performing lookup of entity manager and initiating the particular model implementation with the Person class as entity class and that entity manager.

Sample Code – Page Code

We used two pages there. At first arrangeableModel-sample.xhtml:

<h:form id="form">
    <rich:dataTable keepSaved="true" id="richTable" var="record" 
	value="#{personBean.dataModel}" rows="20">
        <ui:include src="jpaColumn.xhtml">
            <ui:param name="bean" value="#{personBean}" />
        	<ui:param name="property" value="name" />
            </ui:include>
            <ui:include src="jpaColumn.xhtml">
        	<ui:param name="bean" value="#{personBean}" />
        	<ui:param name="property" value="surname" />
            </ui:include>
            <ui:include src="jpaColumn.xhtml">
        	<ui:param name="bean" value="#{personBean}" />
        	<ui:param name="property" value="email" />
            </ui:include>
            <f:facet name="footer">
		<rich:dataScroller id="scroller" />
            </f:facet>
    </rich:dataTable>
</h:form>

Nothing pretty interesting there. We just defining table pointed to our model and including the columns passing properties of the person and the bean to it.

And the second is jpaColumn.xhtml:

<ui:composition>
    <rich:column sortBy="#{property}"
	sortOrder="#{bean.sortOrders[property]}" filterValue="#{bean.filterValues[property]}"
	filterExpression="#{property}">
	<f:facet name="header">
            <h:commandLink action="#{bean.toggleSort}">
            	#{bean.sortOrders[property]}	
            	<a4j:ajax render="richTable" />
            	<f:setPropertyActionListener target="#{bean.sortProperty}" 
		    value="#{property}" />
	     </h:commandLink>
	     <br />
	     <h:inputText value="#{bean.filterValues[property]}">
	         <a4j:ajax render="richTable@body scroller" event="keyup" />
	     </h:inputText>
	</f:facet>
	<h:outputText value="#{record[property]}" />
    </rich:column>
</ui:composition>

That’s actually more interesting for us. Most important what you should note there that we passing just Person properties names as sortBy and filterExpression values. Usually you used EL binding to iteration object property and boolean expression in case you using our default models. But that’s not the case for us. As we implementing our model with in-db sorting and filtering – all we need to know just properties names and we will apply the rules in queries like you could see in the model.

Exercises

That sample is still not ideal for sure. Most important you could easily see that there is absolutely no caching. Every time when walk() or getRowCount() called it queries the db with the request for data. You should add it on your own because there is actually no unified recipe for all the situations. Somebody could need just to read the data from db once when filtering sorting or page changes and be sure that it never changes more between requests. In some cases you should consider that data could be inserted/deleted/edited concurrently by different users so the List obtained in walk() method could be changed even between different walk calls and so on. So it’s up to you to define the rules for that. The same applied to rowCount. It’s highly important to cache it also as possible because it’s called also multiple time during request (by both table and data scroller)

Besides you might want to add Weld/Seam in order to be able to tie beans, entities and services in more graceful way.

The result

Even considering all you could open the demo that blog article would be boring without at least single screenshot of the result we achieved. So here is the table after we performed sorting by surname and filtered by emails to obtain only persons with emails in .com domain:

More information

As usually please refer to RichFaces Documentation to get more info from JavaDoc's and references.

26 comments:
 
12. May 2011, 02:21 CET | Link
gonzalad

Interesting post,

I'm using RF 3.x with Seam 2.

For dataModels, I've never (for now) used RF dataModels. Always found the ExtendedDataModel class too complex and a pity to tie all my code to RF.

I'm using rich:dataTable with a simple LazyDataModel implementing plain javax.faces.model.DataModel such as this one (LazyDataModel.java).

If I look at old primefaces documentation, here's a sample of LazyDataModel usage :

public class CarListController {
  private LazyDataModel<Car> lazyModel;
  public CarListController() {
  /**
  * Test with one hundred million records.
  * In a real application use a count query to get the rowcount.
  */
  lazyModel = new LazyDataModel<Car>(100000000) {
     /**
      * Dummy implementation of loading a certain segment of data.
      * In a real applicaiton, this method should access db and do a limit
      * based query
      */
      @Override
      public List<Car> fetchLazyData(int first, int pageSize) {
        //Query a list of cars starting with offset first and max size
        //pagesize
      }
    };
  }
  public LazyDataModel getLazyModel() {
    return lazyModel;
  }
}

If find this code really simpler.

What I'm overlooking is the RF functionnalities I'm missing doing that (I'm never using directly RF sort features, but I think with sort external, I wouldn't need to use RF ExtendedDataModel).

 
12. May 2011, 11:38 CET | Link
gonzalad

What I'm overlooking is the RF functionnalities I'm missing doing that

Ok, what I missed is the generic JPADataModel you provide in your sample !

With JPADataModel stuff you effectively have in 1 line : lazy db loading, sorting, filtering.

 
16. May 2011, 15:12 CET | Link

This targets which version of RichFaces ? because using this on 4.0.0.Final doesn't works as filterExpression is a boolean to enable/disable filtering.

 
16. May 2011, 19:41 CET | Link
Thorsten
maximilien wrote on May 16, 2011 09:12:
This targets which version of RichFaces ? because using this on 4.0.0.Final doesn't works as filterExpression is a boolean to enable/disable filtering.

I had the same issue. I then changed the RichFaces maven artifacts from 4.0.0.Final to 4.0.1-SNAPSHOT and it started to work. So seems this feature was added some time after the 4.0.0.Final release and will only work with upcoming 4.0.1.

Cheers

 
17. May 2011, 10:49 CET | Link

hi,

Thanks Thorsten i doesn't noticed 4.0.1-SNAPSHOT so i've tried 4.1.0-SNAPSHOT wich was incompatible. Now with 4.0.1-SNAPSHOT all is OK

Maximilien

 
19. May 2011, 14:52 CET | Link

Can you make a complete project and put in a zip file for download? Appreciate!

 
19. May 2011, 15:56 CET | Link

The example richfaces-showcase inside RichFaces 4 download is too complex. I would like to extract the example extendedDataTable and make it run as an independent project. I failed. I developed a very simple project to use extendedDataTable but can not make it work as expected: resize columns, hide columns, nice title etc.

Can you make a simple example and a zip file to download? I can not find any indept RF4 examples online.

 
19. May 2011, 16:10 CET | Link

Guys, sorry for long delay with answers.. But anyway:

1) about the target version - yes it will works in latest snapshots and not in Final

2) to get it build - just checkout the richfaces-showcase demo sources from svn and build with maven.. all the proper libs will be there.

 
04. Sep 2011, 23:09 CET | Link
Lily

Could you kindly provide the code to get this filtering to work with official release 4.0 (the filterExpression that evaluates to boolean).

 
01. Aug 2012, 15:55 CET | Link
Adriaan Wisse | a3aan.wisse(AT)gmail.com

Why is the example not available anymore on the richfaces showcase site?

 
17. Dec 2013, 09:01 CET | Link
HANDBAGS | GWA(AT)GMAIL.COM

According to our knowledge, working with Designer Handbags is unlawful. However, worldwide regulation seems to become less effective in whittling down the revenue of these Handbags Replica products in contemporary market. In that case, more and more watch-making producers take the chance to produce these popular, such as Designer Handbags. Though not designed by approved watch makers,Rolex Replicas greatly are eligible of the mass individuals who desire to encounter the Replica watches luxury of designer timepieces but always limited by limited banking accounts.

 
26. Mar 2014, 12:40 CET | Link
sdddd | sd(AT)gmail.com
Orders for the <a href=http://www.ptwatches.co.uk/>Replica Watches UK</a>
 could be positioned as soon as individuals locate items of their choice. Now, the site is providing amazing deals to customers which purchase two or more <a href=http://www.ptwatches.co.uk/breitling.html>Breitling Replica UK</a>
.
 
26. Mar 2014, 12:41 CET | Link
Most of these Replica Watches are in demand from select groups - which might be why this can be a limited version. Though I do really like the Tremendous Avenger assortment of watches. If you have any queries concerning wherever and how to use disocunt Breitling Replica Watches for, Replica Omega Watches you can speak to us at the internet site.

That gorgeous [url=http://www.ptwatches.co.uk/rolex.html]Rolex Replica Watches[/url]
 look is not complete with an empty wrist, that business lady, that successful man next door and any person who loves [url=http://www.ptwatches.co.uk/]Replica Watches UK[/url]
 is well aware of the [url=http://www.ptwatches.co.uk/breitling.html]Replica Breitling[/url]
, these watches complete your [url=http://www.ptwatches.co.uk/omega.html]Replica Omega Watches[/url]
 look with a smile of satisfaction.
 
26. Mar 2014, 12:43 CET | Link
 
26. Mar 2014, 12:45 CET | Link

Click HELP for text formatting instructions. Then edit this text and check the preview.Hibernate JIRA issue, or a Seam JIRA issue.

Orders for the replica watches could be positioned as soon as individuals locate items of their choice. Now, the site is providing amazing deals to customers which purchase two or more

 
26. Mar 2014, 12:46 CET | Link
sdfsdf | sdf(AT)gmail.com

Orders for thereplica watches could be positioned as soon as individuals locate items of their choice. Now, the site is providing amazing deals to customers which purchase two or more

 
31. May 2014, 19:13 CET | Link

Made from significant top quality PU leather these addresses deliver apt protection to both equally the back again and display within your iPhone. The wallet or perhaps the diary instances are classy with side pockets that allow you to carry cash, credit history, debit and business cards as well as the mobile phone. Thus you will get fashionable, http://www.fashion5case.com/hermes-cases-c-29/ http://www.fashion5case.com/michael-kors-cases-c-38/ http://www.fashion5case.com/prada-cases-c-42/ http://www.fashion5case.com/ipad-2ipad-3-covers-c-7/

 
10. Jun 2014, 16:03 CET | Link
Riggs

In closing, the cheap instagram followers n8 seems to be a great all around phone. They are on the brink of becoming the next Will and Jada Smith. The Studio sometimes launches free giveaway of PDF to Word Converter on facebook.

24. Jun 2014, 11:23 CET | Link

Written for consumers by a consumer, this fan site includes a fun and informative Pure Reiki Healing Mastery review, ebook FAQ, and PDF download guide that provides an insider's look at the program and answers frequently asked questions about Owen Coleman's unique and highly popular Reiki mastery guidepure reiki healing mastery review

25. Jun 2014, 12:11 CET | Link

The Michael Fiore Text Your Ex Back 2.0 PDF and multimedia texting system is here! Read reviews, get download and purchase links, and learn about Michael Fiore text examples and techniques to get your ex back.text your ex back review

26. Jun 2014, 10:41 CET | Link

Practicand cele mai mici preturi de pe piata constructiilor si punandu-va la dispozitie echipe mai numeroase sau mai mici, in functie de cerintele dumneavoastra, reusim sa finalizam orice proiect in limita dumneavoastra de timp, dupa o discutie deschisa si benefica cu dumneavoastra.Amenajari interioare Iasi

12. Jul 2014, 22:05 CET | Link

This site is a leading resource for information about the Linda Allen Yeast Infection No More PDF book that teaches you a unique and rare yeast infection cure to eliminate candida and gain complete relief in as little as 12 Hours.yeast infection no more

17. Jul 2014, 13:11 CET | Link

Your post will be rather good and I'm sure some will find it interesting because it's about a topic that's as widely discussed as others. Some may even find it useful.Thanks so much for your post. Bollywood Calendar

 
30. Aug 2014, 04:10 CET | Link
sfdsa

Walking on the way home, Nike Air Jordan, suddenly a scenery touched, Ralph Outlet, stopped to savor, MCM Outlet Online, to put a camera gesture, Polo Outlet Online, to leave a shallow spring, Gucci Shoes UK, of negatives here, Michael Kors Outlet, deep in her heart extended spring scenery, marc by marc jacobs, etc, returned home, Canada Goose Jackets, using bamboo memo box, Ralph Lauren Outlet, to do with pen, Michael Kors USA, and ink painting, North Jackets Outlet Online, the intention to write, a sweet words, Beats By Dre, do a recall album, wait until old age, Coach Bags Black Friday, come to appreciate slowly, North Clearace Outlet Online, walked with light, Burberry Bags Outlet, footsteps walked on, the King, Monster Headphones Outlet, or the original scene, Longchamp Pairs, people are still the original person, Prada Outlet Online, just change a mood, Michael Kors Outlet Online, all plain people, Cheap Oakley Sunglaases, things, Coach Factory Shop, and it was better together.

 
04. Nov 2014, 04:39 CET | Link

Actually real enterprise application using huge data sets, applies paging with lazy data loading, uses sorting, filtering, selection and the other features which makes then application really rich and interactive. So in most cases you could not rely on simple lists or maps with data wrapped using default models.

 
18. Dec 2014, 15:05 CET | Link
instant payday loans no credit check

Because when you write a book then at least on selling a book you get a percentage. instant payday loans no credit check