3 Replies Latest reply on Jan 23, 2014 4:01 AM by liumin hu

    rich:dataTable and filterExpression : very slow ?

    Mikael Vivier Newbie

      My environment :

      - Richfaces 4.3.4.Final

      - Server Tomcat 6.0.36

       

      Hello,

      I have an application which need a lot of datatables and each datatable need filter and sort !

      For the "filter" part, I use what is recommanded in the "filtering showcase" ie the jstl function in the "filterExpression" of the rich:column (see http://showcase.richfaces.org/richfaces/component-sample.jsf?demo=dataTable&sample=tableFiltering&skin=blueSky)

       

      The problem is that my datatables have a lot of data (10.000 to 100.000) and depending of the server power where my application is deployed, the filter can take ages before rendering the data !

      (after making some tests I am quite sure the problem comes from the jstl function but I don't know how I can do it without using this)

       

      Here is the code of my main.xhtml (note : since there is a lot of datatables, I decide to use the benefits of the ui:composition for columns in my datatables) :

      <rich:dataTable value="#{mainBean.listXXX}" var="xxx" cellpadding="0" cellspacing="0" rows="5"
                      onrowmouseover="jQuery(this).addClass('row-over')" onrowmouseout="jQuery(this).removeClass('row-over')" rowClasses="row-odd,row-even"
                      onrowclick="#{rich:element('rowClickId')}.click();">
          <!-- handle clic on line -->
          <rich:column styleClass="display-none" headerClass="display-none">
              <a4j:commandButton style="display:none" id="rowClickId" render="panelId" execute="@this" action="#{mainController.action}">
                  <f:setPropertyActionListener target="#{mainBean.element}" value="#{xxx}"/>
              </a4j:commandButton>
          </rich:column>
          
          <ui:include src="/common/tables/sortFilterCol.xhtml">
              <ui:param name="label" value="#{AM['label']}"/>
              <ui:param name="field" value="#{xxx.field}"/>
              <ui:param name="key" value="1"/>
              <ui:param name="columnWidth" value="20%"/>
              <ui:param name="columnClass" value="cursorClass"/>
          </ui:include>
      
          ...
      
          <ui:include src="/common/tables/dataScrollerClassic.xhtml"/>
      </rich:dataTable>
      
      

       

      Here is the sortFilterCol.xhtml :

      <ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html"
                      xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:rich="http://richfaces.org/rich" xmlns:a4j="http://richfaces.org/a4j" xmlns:fn="http://java.sun.com/jsp/jstl/functions">     
          <rich:column sortBy="#{field}" sortOrder="#{commonBean.sortOrders[key]}" filterExpression="#{fn:containsIgnoreCase(field,commonBean.filterValues[key])}" 
                       style="width:#{columnWidth}" styleClass="#{columnClass}">
              <f:facet name="header">
                  <h:panelGrid width="100%" columns="2" columnClasses="align-center">
                      <h:panelGrid width="100%">
                          <h:outputText value="#{label}"/>
                          <h:inputText value="#{commonBean.filterValues[key]}" size="#{filterSize != null ? filterSize : 16}">
                              <a4j:ajax event="keyup" render="@body,@footer" execute="@this" status="void"/>
                          </h:inputText>
                      </h:panelGrid>
                      <a4j:commandLink render="@header,@body,@footer" action="#{commonBean.changeSort}" execute="@this" status="void">
                          <h:graphicImage library="common" name="img/sort-#{commonBean.sortOrders[key] != null ? commonBean.sortOrders[key] : 'unsorted'}.png" styleClass="img-sort"/>
                          <f:setPropertyActionListener target="#{commonBean.currentColumn}" value="#{key}"/>
                      </a4j:commandLink>
                  </h:panelGrid>
              </f:facet>
              <h:outputText value="#{field}"/>
          </rich:column>    
      </ui:composition>
      
      

       

      And my commonBean.java :

      private Map<String, String> filterValues;
      private Map<String, SortOrder> sortOrders;
      private String currentColumn;
        
      public void changeSort() {
          if (sortOrders.get(currentColumn) == null) {
              sortOrders.put(currentColumn, SortOrder.unsorted);
          }
          for (Entry<String, SortOrder> entry : this.sortOrders.entrySet()) {
              if (entry.getKey().equals(currentColumn)) {
                  if (entry.getValue().equals(SortOrder.ascending)) {
                      sortOrders.put(currentColumn, SortOrder.descending);
                  } else {
                      sortOrders.put(currentColumn, SortOrder.ascending);
              }
          } else {
              sortOrders.put(entry.getKey(), SortOrder.unsorted);
          }
      }
      
      

       

      If you have any idea, it would be great !

       

      Thanks.

        • 1. Re: rich:dataTable and filterExpression : very slow ?
          liumin hu Master

          there is no sense to show 10000 lines on the browser, you need filter it with server side code.

          • 2. Re: Re: rich:dataTable and filterExpression : very slow ?
            Mikael Vivier Newbie

            Hmm yeah I know, that's why there is datascroller and that's why I want to put filter.

            The data come from my oracle database and the request take 10 seconds so I have to do this only one time...

             

            After some tests, I can see that the problem comes from the jstl function since if I do this in a bean there is no performance issue :

            <rich:column style="width:30%">
                <f:facet name="header">
                    <h:panelGrid width="100%">
                       <h:outputText value="#{AM['label']}"/>
                       <h:inputText value="#{filterBean.name}>
                           <a4j:ajax event="keyup" render="@body,@footer" status="void" listener="#{filterBean.filterTable}"/>
                       </h:inputText>
                    </h:panelGrid>
                </f:facet>
                <h:outputText value="#{xxx.name}"/>
            </rich:column>
            

            But the problem with this solution is that I can't do it in a generic way for every datatables since I need a function for each.

             

            Actually, if I could specify a "filter Method" instead of the "filterExpression" which do the same it would be perfect but I don't know if it's possible...

            • 3. Re: Re: rich:dataTable and filterExpression : very slow ?
              liumin hu Master

              I think the jstl fuction filte your 10000 returned result, that's why it is slow. and there is the example for not using filter expresssion on demo site.