Question

UPDATE II: OK, I managed to narrow it down a little.

I have a page with a datatable with sorting and filtering functionalities, both taking place in the DB. In other words, I do not use the embedded functionality of the rich:datatable I use, but rather let the DB do the work.

I work with request-scoped beans. The only session-scoped beans contain the sorting and filtering of my interface.

Filtering for each column is bound to the certain session bean fields. As such, it is actually updated during the Update Model Values phase.

Sorting required some logic from my part, so I invoke a certain method to set the correct values to the session bean. This is performed during the Invoke Application phase.

So, any changes are in place during the Render Response phase, where the page actually renders.

The problem is that the JSF datatable and datascroller in my page call the backingBean.getDataModel() that fetch the data from the DB and the dataModel.getRowCount() (which I have implemented to invoke a method that runs a separate query) also during the Apply Request Values phase. These two queries take also place during the Render Response Phase, which is the only phase where the changes are all in place, and the query will run normally.

This means that to show a page after I perform filtering or sorting, the double number of queries take place.

I want to perform sorting and filtering only performing the required queries and no more.

Any suggestions?

Was it helpful?

Solution

The getter call during apply request values phase is mandatory because JSF needs to know which input values were initially shown so that it can eventually do any validation and/or call any valuechangelisteners in the next phase where applicable. It is also mandatory to find out which button/link was pressed/clicked in any of the rows so that it knows which bean action to call in the invoke action phase.

But if you don't have any input fields which are to be validated/valuechange-checked nor any buttons/links in any of the rows, then I can imagine that the query during apply request values phase is in your eye completely superfluous.

Unfortunately, you can't completely disable it. Technically, the only resort to that is putting the data bean in the session scope and do the expensive SQL query (and refresh of datamodel) only in the constructor of the bean and in the bean action method, so that it only get invoked during bean's construction (for 1st view) and during bean's action method (during a new sort/filter/whatever request). The disadvantage is however that any changes in the datamodel are reflected in all windows/tabs the enduser has open in the same session, which might cause "wtf?" experiences for the enduser.

Now, Tomahawk was the first which has a nice workaround for this in flavor of the preserveDataModel attribute for the <t:dataTable>, which basically puts the datamodel in the request-specific component tree (which in turn is already stored in the session scope or in a hidden input field in the client side, depending on how you configured the store location of the view state in faces-config). RichFaces doesn't have a direct solution like that, but the <a4j:keepAlive> does basically the same. It would only affect the "whole" bean, thus if your data bean contains more than only the datamodel, you might consider to refactor it. You should keep in mind to design the bean as if it is a session scoped bean.

If the datamodel gets large, then I can imagine that this impacts the server memory, but this shouldn't really harm that much if you only stores the viewable part of the datamodel in memory (and thus not the entire datamodel, including all the other pages). See if it outweighs the cost of firing double SQL queries during a single HTTP request.

Hope this helps.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top