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

    DataModel and DataModelSelection staying populated on select()

    daxxy

      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



        • 1. Re: DataModel and DataModelSelection staying populated on select()
          daxxy

          Oops that title should be NOT staying populated

          • 2. Re: DataModel and DataModelSelection staying populated on select()
            asookazian

            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()
              daxxy
              (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).
              • 4. Re: DataModel and DataModelSelection staying populated on select()
                asookazian

                How are you starting the LRC if at all?

                • 5. Re: DataModel and DataModelSelection staying populated on select()
                  daxxy

                  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()
                    asookazian

                    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)}"