3 Replies Latest reply on Mar 11, 2009 1:20 PM by Vassilis Petropoulos

    Page using EntityQuery executes unwanted queries

    Jivko Mitrev Newbie

      Hi,


      Currently I am using Seam 2.0.2.GA. I have used seam-gen to create the base CRUD pages and entities. It creates pages that have form for search and a panel with table. As a backend it creates an EntityQuery instance for each page. snippet bellow:


      If I access the page by initial request (by link for example) everything works fine. But I have a problems when I make a post-back - when submitting the form by hitting submit button.
      The problem is that I have one or two useless queries instead the one that comes in

       #{cdrList.resultList} 


      Here are two problems that I found.


      1. The first is that I have one useless query instead the one in the Render Response phase. The correct query in the render response t contains the updated values added with the submit.


      The unwanted query is executed as executed for the initial request. It does not contain any data from the submit. It seams that this is done after the post back in the RestoreView Phase of the life cycle when the component model is rebuild, before applying values and running validations.
      If you think that my suggestions are correct please, suggest a fix.



      2. The second one is that there is a separate requests from a same component for each EntityQuery component. May be it is also camming from the ElValueValidation.





        <rich:dataTable id="cdrListTable"
                        var="cdr"
                        value="#{cdrList.resultList}"
                        rendered="#{not empty cdrList.resultList}" >



      Here is a snippet from my xhtml file:


      <h:form id="cdrSearch">
        <rich:simpleTogglePanel label="Call Search parameters" switchType="ajax">
          <s:decorate template="layout/display.xhtml">
            <ui:define name="label" >gsm</ui:define>
              <h:inputText id="gsm" value="#{cdrList.gsm}" />
          </s:decorate>
        </rich:simpleTogglePanel>
        <div class="actionButtons">
          <h:commandButton id="search" action="/CdrList.xhtml" value="Search" />
        </div>
      </h:form>
      
      <rich:panel id="tablePanel" >
        <f:facet name="header">Calls search results</f:facet>
           
        <h:outputText value="The calls search returned no results" 
                      rendered="#{not empty cdrList.resultList}" />
            
        <rich:dataTable id="cdrListTable"
                        var="cdr"
                        value="#{cdrList.resultList}"
                        rendered="#{not empty cdrList.resultList}">
          ...
          <h:column>
            <f:facet name="header" >
              <s:link styleClass="columnHeader" value="number" />
            </f:facet>
            #{cdr.destination}
          </h:column>     
           ...
        </rich:dataTable>
      </rich:panel>



      Here is a snippet from the EnittyQuery class:




      @Name("cdrList")
      public class CdrList extends EntityQuery<CallDetailRecord> {
          /** Constant for maximum results */ 
          private static final int MAX_RESULTS = 25;
          
          private static final String RESTRICTIONS[] = {
              "cdr.destination like concat(#{cdrList.gsm}, '%')",
          };
          
          /** Gsm criteria*/
          private String gsm;
          
          public CdrList() {
              setRestrictions(Arrays.asList(RESTRICTIONS));
          }
          
          /** @see org.jboss.seam.framework.Query#getEjbql()  */
          @Override
          public String getEjbql() {
              return "Select cdr from CallDetailRecord cdr";
          }
      
          /** @see org.jboss.seam.framework.Query#getMaxResults() */
          @Override
          public Integer getMaxResults() {
              return MAX_RESULTS;
          }
      
          public String getGsm() {
              return gsm;
          }
      
          public void setGsm(String gsmArg) {
              this.gsm = gsmArg;
          }
      }




        • 1. Re: Page using EntityQuery executes unwanted queries
          Juan Ignacio Sánchez Lara Apprentice

          Same problem here. Did you make any improvement?

          • 2. Re: Page using EntityQuery executes unwanted queries
            Jivko Mitrev Newbie

            Hi the problem was where I have expected.


            #{cdrList.resultList} 



            Once is evaluated and executed in “Restore View Phase” and once in “Render Response Phase”. It is needed to be executed only in “Render Response Phase”. What I did:


            1.I have made additional method int Component:


            private List<CallDetailRecord> list;
            public List<CallDetailRecord> getList() {
                    return list;
            }



            This component is only returning already found values, by the search criteria. It does not make the db access itself. Only returns value


            2. I have added new method that is making the db access. It is actually calling the method
            from the super class getResultList();



                public void find(){
                    log.debug("[:find] action listener called to find the results!");
                    list = getResultList();
                }



            3.Substitute all the places where


            #{cdrList.resultList}



            is called with


            #{cdrList.list}



            . That way the data base is not called in the “Restore View Phase”


            <rich:dataTable id="cdrListTable"
                      var="cdr"
                      value="#{cdrList.list}"
                      rendered="#{not empty cdrList.list}">


            4.On All the links that I have for sorting/paging I have added action to call my find method. That way find for the new criteria will be made.


            <s:link styleClass="columnHeader"
                 action="#{cdrList.find}"
                    value="...">
                    ...
                 </s:link>



            5. Modify the commandButton to execute the action for finding records.( Do not forget to add navigation in your pages.xml or XXX.page.xml file)


            <h:commandButton id="search" action="#{cdrList.find()}" value="Search" />



            6. Modify the links to that page. If you want to have results initially when going to the page add action attribute that calls your find method. If you do not want initially no data to be shown, but only the “search” form, do not add action.


            <s:link view="/CdrList.xhmlt" 
                    value="some"
                    action="#{cdrList.find}" 
                    propagation="none">
            </s:link>



            I do not know if this is the best solution, but it works for me. I hope that it is going to help you too. There are no additional selects coming from the “Render Response View” phase. If some one have better ideas can share it. (I have to check what is done in seam 2.1.GA)