0 Replies Latest reply on Jul 23, 2009 1:53 AM by Arbi Sookazian

    Using Factory pattern with browser back button bug

    Arbi Sookazian Master

      We found a back button-related bug today in my Seam app that had to do with using @Factory with @DataModel to generate ListDataModel objects for my <rich:dataTable> components.


      User would navigate to page A, click edit link in dataTable for a row, (now the @Factory methods fire for the dataTables in the next JSF page), click browser back button, click edit for a different row.


      The use case is modeled using a LRC so all components (e.g. SFSB backing beans) are CONVERSATION-scoped.  So the bug was that we were seeing cached/stale data in the dataTables for the next page the 2nd time user clicks edit.


      I solved this problem but am not sure it is the best way to solve it.  I added an init() method to the 2nd page's backing bean.  And added a call to that method in my pages.xml:


      <page view-id="/RepairCaseDetails.xhtml">
               <description>Repair Case Details</description>
               <action execute="#{repairCaseDetails.init}"/> 
               <navigation>              
                    <rule if-outcome="cancel">
                         <end-conversation before-redirect="true"/>
                         <redirect view-id="/ManageEquipment.xhtml"/>
                    </rule>
               </navigation>
          </page>



      NOTE: RepairCaseDetails.xhtml is the 2nd JSF page.


      The complication was that I have rich:modalPanel components in the 2nd page and those were making the init() to be executed two times each during load/display phase (possibly due to reRendering as well?)


      So then I added this in the 1st page's backing bean:


      @Out(required=false)
           private Boolean doInitRepairCaseDetails;
      
      public void processRepairHistorySelection()
           {     
                repairId = (Integer)repairHistorySelection[0];
                serialNumber = (String)repairHistorySelection[1];
                doInitRepairCaseDetails = true;
                          
                log.info("in processRepairHistorySelection(): repairId = " + repairId + "; serialNumber = " + serialNumber);
           }



      processRepairHistorySelection() is the method that is executed when user clicks the edit link in 1st page's dataTable edit column.


      Here is the init() method for 2nd page's backing bean:


      //asookazi: set the @DataModel List instances to null so the @Factory methods will fire.
           //this addresses the following bug:      from ManageEquipment page, click edit link in repair history, then click browser back button,
           //then click edit for different row in repair history dataTable, you'll see cached data from previous repairId's dataTables in RepairCaseDetails page.
           public void init()
           {
                if (doInitRepairCaseDetails)
                {
                     repairGeneralInfoList = null;               
                     equipmentRepairFindingCodeList = null;               
                     equipmentRepairProblemCodeList = null;          
                     equipmentRepairCostList = null;
                     totalCost = 0.00;
                     cost = 0.00;
                     doInitRepairCaseDetails = false;
                }
           }



      So now the @Factory methods are only executed after user clicks the edit link, and not when the modalPanels display.


      I have a feeling that this is not a good idea, but it does work:


      @In(required=false)
           @Out(required=false)
           private Boolean doInitRepairCaseDetails;



      Any comments/suggestions?