介紹
當我們需要在任務流消失之前完成一些最終工作(干凈的資源,緊密的連接等)時,這是使用任務流終結器的非常普遍的推薦做法。 和往常一樣,我們使用在任務流中聲明的托管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