DataTable and ajax performance problem
danielrowe Oct 12, 2011 10:05 AMI am using a RichFaces DataTable, and any Ajax-like thing I do (in my case, either setting a transient property on an entity through a checkbox in a data-row, or switching to another page of results using the RichFaces DataScroller), results in ALL of the entities in the backing list being accessed. With a large list (more than a few thousand), this is a major performance problem. Actually, all of the entities are accessed twice.
When I say "accessed", I mean that each entity has all of its getter properties invoked (the setter properties are NOT invoked), even properties that are not displayed in table columns.
I have tried two different paging strategies -- only giving the current page of data to the DataTable -- but the issue is still there (although in both cases, I still had all the items in the list -- I just served them up a page at a time through a custom data-model).
There is something I clearly don't understand about how the data-table works, but others must have faced this issue, so I am hopeful that there is an obvious solution.
Here is a simplified version of my data-table (I removed some of the columns):
<rich:dataTable eventsQueue="default" reRender="dataScroller" styleClass="main-table" id="contactList" rows="20" var="contact" value="#{contacts}" rowClasses="tableRowGrey,tableRowWhite" columnsWidth="33px,130px,130px" columnClasses="rc-liteColumn,rc-liteColumn_lj_pad">
<rich:column>
<h:selectBooleanCheckbox id="deleteCB" required="true" value="#{contact.entitySelected}">
<a4j:support event="onchange" eventsQueue="default" requestDelay="1000" reRender="deleteCB" />
</h:selectBooleanCheckbox>
</rich:column>
<rich:column >
<f:facet name="header">Last Name</f:facet>
<h:outputText>#{contact.lastName}</h:outputText>
</rich:column>
<rich:column >
<f:facet name="header">First Name</f:facet>
<h:outputText>#{contact.firstName}</h:outputText>
</rich:column>
</rich:dataTable>
In my manager bean (stateless), the list of entities:
// Bijected list of contacts (the active contact list)
@In(required = false, scope = ScopeType.CONVERSATION) @Out(required = false, scope = ScopeType.CONVERSATION)
protected List<Contact> contacts;
And a factory method (which is only called once):
@Factory("contacts")
@Restrict("#{identity.loggedIn}")
public void getContacts() {
Long groupID = (activeContactList != null) ? activeContactList.getId() : null;
contacts = ContactListCommon.getContacts(entityManager, standardAccount.getId(), groupID);
}
When I say "accessed", I mean that each entity has all of its getter properties invoked (the setter properties are NOT invoked), even properties that are not displayed in table columns.
I have tried two different paging strategies -- only giving the current page of data to the DataTable -- but the issue is still there (although in both cases, I still had all the items in the list -- I just served them up a page at a time through a custom data-model).
There is something I clearly don't understand about how the data-table works, but others must have faced this issue, so I am hopeful that there is an obvious solution.
Here is a simplified version of my data-table (I removed some of the columns):
<rich:dataTable eventsQueue="default" reRender="dataScroller" styleClass="main-table" id="contactList" rows="20" var="contact" value="#{contacts}" rowClasses="tableRowGrey,tableRowWhite" columnsWidth="33px,130px,130px" columnClasses="rc-liteColumn,rc-liteColumn_lj_pad">
<rich:column>
<h:selectBooleanCheckbox id="deleteCB" required="true" value="#{contact.entitySelected}">
<a4j:support event="onchange" eventsQueue="default" requestDelay="1000" reRender="deleteCB" />
</h:selectBooleanCheckbox>
</rich:column>
<rich:column >
<f:facet name="header">Last Name</f:facet>
<h:outputText>#{contact.lastName}</h:outputText>
</rich:column>
<rich:column >
<f:facet name="header">First Name</f:facet>
<h:outputText>#{contact.firstName}</h:outputText>
</rich:column>
</rich:dataTable>
In my manager bean (stateless), the list of entities:
// Bijected list of contacts (the active contact list)
@In(required = false, scope = ScopeType.CONVERSATION) @Out(required = false, scope = ScopeType.CONVERSATION)
protected List<Contact> contacts;
And a factory method (which is only called once):
@Factory("contacts")
@Restrict("#{identity.loggedIn}")
public void getContacts() {
Long groupID = (activeContactList != null) ? activeContactList.getId() : null;
contacts = ContactListCommon.getContacts(entityManager, standardAccount.getId(), groupID);
}