6 Replies Latest reply on Aug 7, 2009 1:49 AM by Arbi Sookazian

    DataModel and DataModelSelection staying populated on select()

    Tanya Ruttenberg Expert

      I have the following class:




      @Scope(ScopeType.CONVERSATION)
      @Name("iosBreakdownList")
      public class IosBreakdownList {
           
           @In(create=true)
           private EntityManager entityManager;
           
           @DataModel
           private List<Object[]> iosVersions;
           
           @DataModelSelection
           @Out(required=false)
           private Object[] selectedIosVersion;
      
           public List<Object[]> getIosVersions() {
                List<Object[]> resultList = entityManager.createQuery("select d.devOsVer, count(*) from Devices d " +
                "where d.devOsVer != 'Error' group by d.devOsVer").getResultList();
                iosVersions = resultList;
                return iosVersions;
           }
      
           public String select(){
                return "os_selected";
           }
           
           @Remove
           public void destroy(){
           }
      }




      The data is displayed in a datatable:




      <rich:dataTable id="iosBreakdownList" var="_ios"
              value="#{iosBreakdownList.iosVersions}"
              rowClasses="rvgRowOne,rvgRowTwo">
              <rich:column width="500px">
                <f:facet name="header">
                  <h:outputText value="#{messages['ond.label.devosver']}" />
                </f:facet>
                <s:link action="#{iosBreakdownList.select()}" value="#{_ios[0]}"></s:link>
              </rich:column>
              <rich:column width="100px">
                <f:facet name="header">
                  <h:outputText value="Count" />
                </f:facet>
                <h:outputText value="#{_ios[1]}" />
              </rich:column>
            </rich:dataTable>




      I am watching the flow of things in the debugger and I don't understand what I'm seeing.  I have breakpoints on getIosVersions and select.  When I render the page, getIosVersions is called several times.  On the 2nd and subsequent times of calling it, selectedIosVersion is populated.


      When I click on the link on the link, I jump to the breakpoint in my select() and both iosVersions and selectedIosVersions are null.  The page simply rerenders at that point, which is OK for now.  Ultimately I want to redirect to a new view using the selectedIosVersion as the input parameter.


      But first I have to make sure I can even access iosVersions and selectedIosVersion.


      Why is getIosVersion getting called multiple times?
      Why is selectedIosVersion getting set when I haven't selected anything yet?
      How are these things not hanging on to their content by the time I call select?


      TDR



        • 2. Re: DataModel and DataModelSelection staying populated on select()
          Arbi Sookazian Master

          There is always a temporary conversation in Seam.  I'm assuming there is no LRC in this case (unless there is a <begin-conversation/> tag in pages.xml for this particular action.


          Try adding @Begin(join=true) to getIosVersions() to see if that makes a difference in terms of the number of calls to that method.


          This is incorrect:


          @DataModel
               private List<Object[]> iosVersions;
               
               @DataModelSelection
               @Out(required=false)
               private Object[] selectedIosVersion;
          
               public List<Object[]> getIosVersions() {
                    List<Object[]> resultList = entityManager.createQuery("select d.devOsVer, count(*) from Devices d " +
                    "where d.devOsVer != 'Error' group by d.devOsVer").getResultList();
                    iosVersions = resultList;
                    return iosVersions;
               }
          



          do this instead:


          @DataModel
               private List<Object[]> iosVersions;
               
               @DataModelSelection
               @Out(required=false)
               private Object[] selectedIosVersion;
          
               public void getIosVersions() {
                    iosVersions = entityManager.createQuery("select d.devOsVer, count(*) from Devices d " +
                    "where d.devOsVer != 'Error' group by d.devOsVer").getResultList();
                    
               }
          



          Because @DataModel outjects a ListDataModel, there is no need for the getIosVersions() method to return an Object.


          As a quick check, I tried the following code:


          xhtml:


          <rich:dataTable id="breakdownList" var="_platform"
                        value="#{insertAppSite.startup()}">
                        <rich:column>
                              <h:outputText value="#{_platform[0]}" />
                        </rich:column>
                        <rich:column>
                             <h:outputText value="#{_platform[1]}" />
                        </rich:column>
                    </rich:dataTable>



          with the following component backing bean:


          @Stateful
          @Name("insertAppSite")
          @Scope(ScopeType.CONVERSATION)
          public class TestStartupInsertApplicationSite implements TestStartupInsertApplicationSiteLocal {
          
               @In
               private EntityManager entityManager;
               
               @Logger
               private Log log;
               
               @DataModel
               private List<Object[]> resultCount;
               
               //@Begin(join=true)
               public void startup(){
                    
                    resultCount = entityManager.createQuery("select e.modelNumber, count(*) from Equipment e group by e.modelNumber").getResultList();
                    
                    log.info("resultCount.size() = "+resultCount.size());
                    
                    
               }
               
               @End(beforeRedirect=true)
               public void end(){
                    //no op
               }
               
               @Destroy @Remove
               public void destroy(){
                    log.info("in "+this.getClass().getName()+".destroy()");
               }
          }



          And it hit the startup() method only once with or w/o the @Begin(join=true).  So I'm not exactly sure why your backing bean method is being executed multiple times per HTTP request/response cycle (this does happen with getter methods that are bound to the rendered JSF attribute).


          Is the <rich:dataTable> in a loop somehow like nested inside a <a4j:repeat>?

          • 3. Re: DataModel and DataModelSelection staying populated on select()
            Tanya Ruttenberg Expert
            (Giving up on formatted text. Argh)

            Thanks again for helping me Arbi.

            When I do a simple listing, like you have, getIosVersions is only called once to get the list.

            When I replace h:outputText with a link that will allow me to select one of the options in the list, it is called 31 times, seemingly once for each os version (select count distinct dev_os results in 31) and selectedOsVersion is populated, though with the same result each time.

            In other words, when I have this:

                <h:outputText value="#{_ios[0]}" />

            getIosVersions is called once. As soon as I replace it with this:


                <s:link action="#{iosBreakdownList.select()}" value="#
            {_ios[0]}"/>


            It gets called once for each distinct occurence of osVersion (31 times in this case).
            • 5. Re: DataModel and DataModelSelection staying populated on select()
              Tanya Ruttenberg Expert

              Not starting it at all.


              I decided to scrap my idea of using DataModelSelection, which was the ultimate goal here and now I simply pass the selection to the new view as a parameter.





              <s:link view="/ONDDevResultPage" value="#{_ios[0]}" >
                     <f:param name="osver" value="#{_ios[0]}"/>
              </s:link>






              Though that does not solve the question of why the query is running so many times.

              • 6. Re: DataModel and DataModelSelection staying populated on select()
                Arbi Sookazian Master

                I've had issues with @DataModelSelection when the dataTable is sorted.


                You can get the rowIndex of the dataTable and pass that via JBoss EL instead.


                action="#{bean.foo(rowIndex)}"