3 Replies Latest reply on Nov 19, 2009 2:35 AM by trelieux

    EntityQuery ResultList Search and Pagination

    trelieux

      Hello,


      When doing a search through a resultlist in a RichFaces datatable (which was paginated with a datascroller).  I noticed  that when I do a search on the first page of the datatable I can find any result with a valid search.  But if I scroll to the last page on the datable and do the same search, I get no results as it can no longer find that valid item.  My question is what can I do to ensure that no matter what page the user is on they'll be able to search the entire resultlist in the datatable no matter what page their on in the datatable.  For example if I'm on page 9 of the datatable resultList and I want to do search where the item is actually located on page 1, if I do a valid search query in a text inputfield the resultlist should still be able to find the result from page 1, even though I'm on page 9 of the datatable?  Does that make sense?  If not I will attempt to clarify some more.  Here is a example sessionlist bean I'm using to generate a resultlist for a datatable:



      @Name("exoshellUserRolesList")
      @Scope(ScopeType.SESSION)
      public class ExoshellUserRolesList extends EntityQuery<ExoshellUserRoles> {
           @In
           protected EntityManager entityManager;     
           
           /* UNABLE TO GET RESTRICTIONS TO WORK WITHOUT POINTING TO NULL PARENT OBJECT I.E. exoshellUsers, exoshellRoles or exoshellModules */
           private static final String[] RESTRICTIONS = {
                "lower(exoshellUserRoles.exoshellUsers.username) like concat(lower(#{exoshellUserRolesList.exoshellUserRoles.exoshellUsers.username}),'%')",
                "lower(exoshellUserRoles.exoshellRoles.roleName) like concat(lower(#{exoshellUserRolesList.exoshellUserRoles.exoshellRoles.roleName}),'%')",
                "lower(exoshellUserRoles.exoshellModules.moduleName) like concat(lower(#{exoshellUserRolesList.exoshellUserRoles.exoshellModules.moduleName}),'%')"
           };     
           
           private ExoshellUserRoles exoshellUserRoles = new ExoshellUserRoles(); 
           @In(create=true)
           private ExoshellUsersHome exoshellUsersHome;
           @In(create=true)
           private ExoshellRolesHome exoshellRolesHome;
           @In(create=true)
           private ExoshellModulesHome exoshellModulesHome;
           private String queryString = new String("select exoshellUserRoles from ExoshellUserRoles exoshellUserRoles " +
                     "join fetch exoshellUserRoles.exoshellUsers " +
                     "left join fetch exoshellUserRoles.exoshellRoles " +
                     "left outer join fetch exoshellUserRoles.exoshellModules ");
      
           public ExoshellUserRolesList() {   
                      setEjbql(queryString);
           }
                
           @Override
           public String getEjbql() {
                return queryString;
           }
      
           public ExoshellUserRoles getExoshellUserRoles() {
                 if (exoshellUserRoles.getExoshellUsers() == null){
                      exoshellUserRoles.setExoshellUsers(exoshellUsersHome.getInstance());
                 }  
                 if (exoshellUserRoles.getExoshellRoles() == null){
                      exoshellUserRoles.setExoshellRoles(exoshellRolesHome.getInstance());
                 }  
                 if (exoshellUserRoles.getExoshellModules() == null){
                      exoshellUserRoles.setExoshellModules(exoshellModulesHome.getInstance());
                 }  
                return exoshellUserRoles;
           }
      
           @Override
           public List<String> getRestrictions() {
                return Arrays.asList(RESTRICTIONS);
           }
      
           @Override
           public String getOrder() {
                return new String("exoshellUserRoles.userRolesId asc");
           }
           
          @Override
          public EntityManager getPersistenceContext()
          {
            return entityManager;
          }
      
      }




      Here is my FrontEnd.




      ...
                  <s:decorate template="/layout/display.xhtml">
                      <ui:define name="label">User Name</ui:define>
                      <h:inputText id="userRoleName" value="#{exoshellUserRolesList.exoshellUserRoles.exoshellUsers.username}">
                       <a:support event="onblur" reRender="panel1,userRolesPaginator"/> 
                      </h:inputText>
                  </s:decorate>
      
                  <s:decorate template="/layout/display.xhtml">
                      <ui:define name="label">Role Name</ui:define>
                      <h:inputText id="userRoleRolename" value="#{exoshellUserRolesList.exoshellUserRoles.exoshellRoles.roleName}">
                       <a:support event="onblur" reRender="panel1,userRolesPaginator"/> 
                      </h:inputText>
                  </s:decorate> 
       
                  <s:decorate template="/layout/display.xhtml">
                      <ui:define name="label">Module</ui:define>
                      <h:inputText id="userRoleModule" value="#{exoshellUserRolesList.exoshellUserRoles.exoshellModules.moduleName}">
                       <a:support event="onblur" reRender="panel1,userRolesPaginator"/> 
                      </h:inputText>
                  </s:decorate>           
              </rich:simpleTogglePanel>
                
                <br/>   
                  
          <rich:panel id="panel1">
              <f:facet name="header">UserRoles results</f:facet>
           <h:outputText value="The UserRoles search returned no results." 
                     rendered="#{empty exoshellUserRolesList.resultList}"/>
                     
          <rich:dataTable id="exoshellUserRolesList" 
                      var="_exoshellUserRoles"
                    value="#{exoshellUserRolesList.resultList}" 
                 rendered="#{not empty exoshellUserRolesList.resultList}" rows="10" binding="#{userRolesDataTable.dataTable}">
              <rich:column>
                  <f:facet name="header">User Role Id</f:facet>
                  <h:outputText value="#{_exoshellUserRoles.userRolesId}"/>
              </rich:column>
              <rich:column>
                  <f:facet name="header">User Name</f:facet>
                  <h:outputText value="#{_exoshellUserRoles.exoshellUsers.username}"/>
              </rich:column>
              <rich:column>
                  <f:facet name="header">Role Name</f:facet>
                  <h:outputText value="#{_exoshellUserRoles.exoshellRoles.roleName}"/>
              </rich:column>
              <rich:column>
                  <f:facet name="header">Module</f:facet>
                  <h:outputText value="#{_exoshellUserRoles.exoshellModules.moduleName}"/>
              </rich:column>
              <rich:column>
                  <f:facet name="header">Action</f:facet>
                  <h:outputLink value="#{facesContext.externalContext.requestContextPath}/admin/ExoshellUserRolesEdit.seam">
                     <f:verbatim>Select</f:verbatim>
                     <f:param name="exoshellUserRolesUserRolesId" 
                              value="#{_exoshellUserRoles.userRolesId}"/>
                  </h:outputLink>
              </rich:column>
          </rich:dataTable>
          </rich:panel>  
          <rich:datascroller id="userRolesPaginator" maxPages="5"  for="exoshellUserRolesList" renderIfSinglePage="false" eventsQueue="userRolesQueue" ignoreDupResponses="true" requestDelay="1000">         
          </rich:datascroller>



          

        • 1. Re: EntityQuery ResultList Search and Pagination

          Are you aware that if you paginate with datascroller unless you do something like this, as the number of records in your table increases, your performance will decrease until your application finally collapses?

          • 2. Re: EntityQuery ResultList Search and Pagination
            trelieux

            Francisco,


            That is kind of strange to me because I would of thought the RichFaces component by default especially when used with Seam for Enterprise applications would be able via attributes or maybe with very little native backend api methods be able to handle huge number of records ( greather than 1000000) and be able to traverse the records easily with very little customization on the Developers part.  That solution you linked to could almost be it's own mini-framework.  I'm not critizing the solution it's just that I'm very surprised no one on the RichFaces / Seam team(s) had created a more high level/easy api for the datascroller to scale well when handling  a huge number of records.  Well I sincerely thank you for your response and insight into this issue and will try to implement that solution into my application(s).

            • 3. Re: EntityQuery ResultList Search and Pagination
              trelieux

              I take back my previous comment I now see that you are extending the ExtendedDataModel to add the necessary logic to grab the necessary rows chunk by chunks and not all at once.