Using Factory pattern with browser back button bug
asookazian Jul 23, 2009 1:53 AMWe 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?