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?