ADF Task Flow: Managed bean scopes for page fragments
Let’s say I have some simple task flow template task-flow-template.xml:
<managed-bean id="__5"> <managed-bean-name id="__3">viewBean</managed-bean-name> <managed-bean-class id="__2">com.cs.blog.ViewBean</managed-bean-class> <managed-bean-scope id="__4">request</managed-bean-scope> </managed-bean> <managed-bean id="__15"> <managed-bean-name id="__13">flowBean</managed-bean-name> <managed-bean-class id="__12">com.cs.blog.FlowBean</managed-bean-class> <managed-bean-scope id="__14">pageFlow</managed-bean-scope> </managed-bean> <view id="MainView"> <page>/MainView.jsff</page> </view>
It has one view activity MainView and two backing beans. The flowBean has pageFlow scope and is responsible to store flow information. The viewBean has request scope (we will play with that) and it services the ManView view activity.
The flowBean has the following method returning the tittle of the task flow:
public String getFlowTitle() { return null; }
The viewBean has some string field testString to store input value:
protected String testString; public void setTestString(String testString) { this.testString = testString; } public String getTestString() { return testString; }
The MainView shows the task flow’s title and has an inputText for the testString. It looks like this:
We also have two task flows built on the task-flow-template – first-flow-definition and second-flow-definition. They have overridden managed beans.
For the first-flow-definition:
<managed-bean id="__5"> <managed-bean-name id="__3">viewBean</managed-bean-name> <managed-bean-class id="__21">com.cs.blog.FirstViewBean</managed-bean-class> <managed-bean-scope id="__4">request</managed-bean-scope> </managed-bean> <managed-bean id="__15"> <managed-bean-name id="__13">flowBean</managed-bean-name> <managed-bean-class id="__12">com.cs.blog.FirstFlowBean</managed-bean-class> <managed-bean-scope id="__14">pageFlow</managed-bean-scope> </managed-bean>
public class FirstFlowBean extends FlowBean { public FirstFlowBean() { super(); } public String getFlowTitle() { return "FirstFlow"; } }
public class FirstViewBean extends ViewBean { public FirstViewBean() { super(); } @PostConstruct public void init() { testString = "FirstFlow"; } }
So the title and default value for testString is “FirstFlow”.
For the second-flow-definition:
<managed-bean id="__5"> <managed-bean-name id="__3">viewBean</managed-bean-name> <managed-bean-class id="__21">com.cs.blog.SecondViewBean</managed-bean-class> <managed-bean-scope id="__4">request</managed-bean-scope> </managed-bean> <managed-bean id="__15"> <managed-bean-name id="__13">flowBean</managed-bean-name> <managed-bean-class id="__12">com.cs.blog.SecondFlowBean</managed-bean-class> <managed-bean-scope id="__14">pageFlow</managed-bean-scope> </managed-bean>
public class SecondFlowBean extends FlowBean { public SecondfFowBean() { super(); } public String getFlowTitle() { return "SecondFlow"; } }
public class SecondViewBean extends ViewBean { public SecondViewBean() { super(); } @PostConstruct public void init() { testString = "SecondFlow"; } }
So the title and default value for testString is “SecondFlow”.
Ok. It’s time to experiment. Let’s put on our page two regions with first-flow-definition and second-flow-definition task flows:
<af:region value="#{bindings.firstflowdefinition1.regionModel}" id="r1"/> <af:separator id="s1"/> <af:region value="#{bindings.secondflowdefinition1.regionModel}" id="r2" />
requestScope
Leaving the scope for the viewBean as requestScope we will get the following result:
In the SecondFlow we see the testString from the FirstViewBean instance. We can have only one instance of the requestScope bean per request. The viewBean was created for the FirstFlow task flow and the same instance was used again for the SecondFlow.
backingBeanScope
And, Yes, the backingBeanScope has fixed the problem. We have two instances of the viewBean – for the regions r1 and r2.
But let’s make the first-flow-definition task flow a bit more complicated:
Now we can call child task flow (of the same definition) from the MainView. And let’s repeat the experiment. On the initial rendering:
So far, so good. Let’s input something in the input text of the FirstFlow and press “call child task flow”:
viewScope
And now let’s change the viewBean’s scope to the viewScope and have the same experiment. On the initial rendering:
Ok. Inputting the same garbage in the inputText:
And pressing the “call child task flow”:
That’s it!
Reference: Managed bean scopes for page fragments in ADF Task Flow from our JCG partner Eugene Fedorenko at the ADF Practice blog.