我們正在使用JSF 2,Spring和Hibernate構建應用程序。 MyFaces Orchestra被用來提供我們用於應用程序中大部分頁面的對話範圍(以利用Orchestra對Hibernate Session的管理)。我們所有的bean都被聲明爲使用conversation.access作用域(根據Orchestra文檔)應該意味着只要用戶導航到不包含對該支持bean實例的任何引用的頁面,bean就會從作用域中移除。使用MyFaces Orchestra時,conversation.access beans在導航到不同視圖時未被刪除
我遇到的問題是,如果我從視圖中導航而不顯式地使對話失效,如果他們以後再回到該視圖,它仍然具有與以前相同的數據。我在所有支持bean中實現了ConversationBindingListener方法,並且可以看到它們何時從對話中移除,並且我可以看到它們在很多情況下都不是。
是什麼讓問題變得更加困惑的是,當我導航到某些頁面(視圖)而不是其他人時,支持bean被刪除。我想也許這是因爲頁面有一個意外的引用到EL中的其他支持bean,但我無法找到任何。我也認爲,也許這個問題只發生在我從一個有對話的頁面導航時。使用不同的conversation.scoped bean將scoped bean訪問到另一個頁面。但是,從對話中刪除的情況下,該頁面還包含對conversation.access作用域bean的引用。
正如我早說的,使用Conversation.getCurrentInstance()。invalidate()函數明確地使對話無效。但是,明確地使會話失效對每個用例都是不可能的,因爲用戶只需點擊其中一個導航鏈接就可以留下視圖,這是非常常見的用例。我們使用Hibernate 3.6(而不是JPA),這意味着我們不得不使用HibernatePersistenceContextFactory。
- MyFaces的樂團 (MyFaces的樂團-core20-1.4.jar)
- JSF 2(鑽嘴魚科2.0.4)
- 春季3.0
- PrimeFaces 2.2.1
- RichFaces的4.0.0
下面是我的Spring上下文配置看起來像(Orchestra)。
<!-- 1. initialization of all orchestra modules (required for core15 module) -->
<import resource="classpath*:/META-INF/spring-orchestra-init.xml" />
<!-- 2. the conversation scopes -->
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
<map>
<entry key="conversation.manual">
<bean
class="org.apache.myfaces.orchestra.conversation.spring.SpringConversationScope">
<property name="timeout" value="30" />
<property name="advices">
<list>
<ref bean="persistentContextConversationInterceptor" />
</list>
</property>
</bean>
</entry>
<entry key="conversation.access">
<bean
class="org.apache.myfaces.orchestra.conversation.spring.SpringConversationScope">
<property name="timeout" value="30" />
<property name="advices">
<list>
<ref bean="persistentContextConversationInterceptor" />
</list>
</property>
<property name="lifetime" value="access" />
</bean>
</entry>
</map>
</property>
</bean>
<!-- 3. the "entity manager" manager -->
<bean id="persistentContextConversationInterceptor"
class="org.apache.myfaces.orchestra.conversation.spring.PersistenceContextConversationInterceptor">
<property name="persistenceContextFactory" ref="persistentContextFactory" />
</bean>
<!-- 4. conversation - persistence adapter -->
<bean id="persistentContextFactory"
class="com.acme.infra.orchestra.hibernate.HibernatePersistenceContextFactory">
<property name="entityManagerFactory" ref="sessionFactory" />
</bean>
<!-- 5. persistence -->
<bean id="managedDataSource"
class="org.apache.myfaces.orchestra.connectionManager.ConnectionManagerDataSource">
<property name="dataSource" ref="dataSource" />
</bean>
這裏有幾個JSF輔助bean聲明的例子。
<bean id="quoteSummaryBackingBean" class="com.acme.ui.backing.QuoteSummaryBackingBean"
scope="conversation.access" orchestra:conversationName="QuoteSummaryConversation">
<property name="quotingBusinessService" ref="quotingBusinessService"/>
<property name="customerBusinessService" ref="customerBusinessService"/>
<property name="referenceDataBusinessService" ref="referenceDataBusinessService"/>
<property name="quoteExportBusinessService" ref="quoteExportBusinessService" />
</bean>
<bean id="createQuoteBackingBean" class="com.acme.ui.backing.CreateQuoteBackingBean"
scope="conversation.access" orchestra:conversationName="CreateQuoteConversation">
<property name="quotingBusinessService" ref="quotingBusinessService"/>
<property name="customerBusinessService" ref="customerBusinessService"/>
<property name="referenceDataBusinessService" ref="referenceDataBusinessService"/>
更新:我發現這個問題在導航到使用標記時顯示。出於某種原因,在下一個視圖中出現會觸發一個條件,導致Orchestra *從對話中刪除前一個視圖的支持bean。相關的代碼在Orchestra的AccessScopePhaseListener中;它設置一個名爲org.apache.myfaces.orchestra.conversation.jsf.AccessScopePhaseListener:oldView的請求作用域變量,當此變量的值與當前視圖匹配時,Orchestra跳過清理未使用組件的任務。 –