介绍
当我们需要在任务流消失之前完成一些最终工作(干净的资源,紧密的连接等)时,这是使用任务流终结器的非常普遍的推荐做法。 和往常一样,我们使用在任务流中声明的托管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";elsereturn "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 instancesSystem.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时要特别小心,尤其是在终结器中访问它们时。 但在任何情况下,你可以使用所描述的同样的伎俩以前的帖子 。
而已!
参考:来自ADF实践博客上的JCG合作伙伴 Eugene Fedorenko 在ADF任务流终结器中支持bean作用域 。
翻译自: https://www.javacodegeeks.com/2012/05/adf-backing-bean-scope-in-task-flow.html