介绍
当我们需要在任务流消失之前完成一些最终工作(干净的资源,紧密的连接等)时,这是使用任务流终结器的非常普遍的推荐做法。
和往常一样,我们使用在任务流中声明的托管bean。
托管Bean可以具有不同的范围-请求,页面流,视图,支持Bean等。该范围取决于该Bean的实际用途。
当我们访问终结器中的backingBean范围托管的bean时,存在一个小问题。
让我们看看下面的示例。
我们有一个包含页面片段的有限任务流:
而且,我们在三个不同范围的任务流中对bean进行了管理-页面流,视图和backingBean:
<managed-bean id="__3">
<managed-bean-name id="__5">FlowBean</managed-bean-name>
<managed-bean-class id="__4">view.BackBean</managed-bean-class>
<managed-bean-scope id="__2">pageFlow</managed-bean-scope>
</managed-bean>
<managed-bean id="__9">
<managed-bean-name id="__6">ViewBean</managed-bean-name>
<managed-bean-class id="__7">view.BackBean</managed-bean-class>
<managed-bean-scope id="__8">view</managed-bean-scope>
</managed-bean>
<managed-bean id="__10">
<managed-bean-name id="__11">BackBean</managed-bean-name>
<managed-bean-class id="__12">view.BackBean</managed-bean-class>
<managed-bean-scope id="__13">backingBean</managed-bean-scope>
</managed-bean>
在页面上,我们有三个按钮绑定到每个范围的托管Bean:
<af:commandButton text="commandButton 1" id="cb1"
action="go" binding="#{backingBeanScope.BackBean.button}">
</af:commandButton>
<af:commandButton text="commandButton 1" id="cb2"
binding="#{viewScope.ViewBean.button}"/>
<af:commandButton text="commandButton 1" id="cb3"
binding="#{pageFlowScope.FlowBean.button}"/>
Bean类具有button属性和testString属性,用于指示是否分配了按钮:
private RichCommandButton button;
public void setButton(RichCommandButton button)
{
this.button = button;
}
public RichCommandButton getButton()
{
return button;
}
public String getTestString()
{
if (this.button == null)
return "The button is not assigned";
else
return "The button is assigned";
}
当我们按下cb1时,我们进入return活动,并且终结器被执行:
public static String resolveExpression(String expression)
{
FacesContext fc = FacesContext.getCurrentInstance();
return (String) fc.getApplication().evaluateExpressionGet(fc, expression,
String.class);
}
public void theFinalizer()
{
//Just to have test access to the managed beans
//and to be sure we work with the same instances
System.out.println(resolveExpression("#{pageFlowScope.FlowBean.testString}")+
" " + resolveExpression("#{pageFlowScope.FlowBean.button}"));
System.out.println(resolveExpression("#{viewScope.ViewBean.testString}")+
" " + resolveExpression("#{viewScope.ViewBean.button}"));
System.out.println(resolveExpression("#{backingBeanScope.BackBean.testString}")+
" " + resolveExpression("#{backingBeanScope.BackBean.button}"));
}
运行该应用程序,按cb1按钮,然后在系统日志中查看以下内容:
为按钮分配了RichCommandButton [UIXFacesBeanImpl,id = cb3]
为按钮分配了RichCommandButton [UIXFacesBeanImpl,id = cb2]
为按钮分配了RichCommandButton [UIXFacesBeanImpl,id = cb1]
一切似乎都还好。
任务流程已完成,在终结器中,我们将使用正确的托管Bean实例。
在此测试中,使用Return活动正确完成了任务流。
现在,让我们放弃我们的任务流程–只是离开任务流程所在的页面。
终结器也将执行,并查看系统输出:
为按钮分配了RichCommandButton [UIXFacesBeanImpl,id = cb3]
为按钮分配了RichCommandButton [UIXFacesBeanImpl,id = cb2]
未分配按钮
这意味着我们将使用backingBeanScope.BackBean的不同实例!
万一任务流过多,控制器在终结器中看不到正确的backingBeanScope,它为空,并且控制器创建BackBean的新实例。
同时pageFlowScope和viewScope工作完美。
因此,在任务流中使用backingBean范围管理的bean时要特别小心,尤其是在终结器中访问它们时。
但在任何情况下,你可以使用所描述的同样的伎俩以前的帖子 。
而已!
翻译自: https://www.javacodegeeks.com/2012/05/adf-backing-bean-scope-in-task-flow.html