2015-02-07 32 views
2

當我關閉服務器時,我有一些作業正在填充下載和填充數據,我希望允許它們優雅地完成。在關閉EntityManagerFactory之前添加運行關閉鉤子的Spring/Hibernate

我試着添加一個Runtime.getRuntime()。addShutDownHook(),但是這似乎在Entitymanager已經關閉之後運行,因爲在運行之前異常開始涌入。

然後我試圖將它添加到實現的ServletContextListener和

@Override 
public void contextDestroyed(ServletContextEvent servletContextEvent) 

其關閉前的勾跑了,但還是之後的EntityManager已經關閉。

有沒有辦法在entitymanager關閉之前運行一些邏輯?

我注射用

@Configuration 

@Bean(name= PERSISTENCE_UNIT) 
.... createEntityManagerFactory() 

我怎樣才能正確地聽,當了EntityManager被關閉使用

@PersistenceContext(unitName = PERSISTENCE_UNIT) 
private EntityManager entityManager; 

創建EntityManagerFactory的EntityManager的,這樣我就可以讓掛起的工作完成第一?

我在使用Web模塊的Java EE上使用Spring,Hibernate,JPA。

產生的例外是:

java.lang.IllegalStateException: EntityManagerFactory is closed 
     org.hibernate.jpa.internal.EntityManagerFactoryImpl.validateNotClosed(EntityManagerFactoryImpl.java:388) 
     org.hibernate.jpa.internal.EntityManagerFactoryImpl.internalCreateEntityManager(EntityManagerFactoryImpl.java:342) 
     org.hibernate.jpa.internal.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:313) 
     sun.reflect.GeneratedMethodAccessor62.invoke(Unknown Source) 
     sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
     java.lang.reflect.Method.invoke(Method.java:497) 
     org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.invokeProxyMethod(AbstractEntityManagerFactoryBean.java:388) 
     org.springframework.orm.jpa.AbstractEntityManagerFactoryBean$ManagedEntityManagerFactoryInvocationHandler.invoke(AbstractEntityManagerFactoryBean.java:541) 
     com.sun.proxy.$Proxy51.createEntityManager(Unknown Source) 
     org.springframework.orm.jpa.EntityManagerFactoryUtils.doGetTransactionalEntityManager(EntityManagerFactoryUtils.java:285) 
     org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:252) 
     com.sun.proxy.$Proxy53.getDelegate(Unknown Source) 

回答

0

就這麼弄的該EntityManagerFactory當Spring應用程序上下文被銷燬關閉。

根據您記錄的異常情況,主要運行線程檢測到應用程序銷燬事件,Spring shutdownHook將destroy事件傳播到所有註冊的bean,包括EntityManagerFactory

您可能有一個批處理作業有一些工作線程,它們不聽應用程序銷燬事件並因此繼續執行,因此嘗試使用關閉的EntityManagerFactory創建EntityManager

由於應用程序上下文被破壞,它不僅僅是關閉的EntityManagerFactory,還有TransactionManagerDataSource。這就是爲什麼你可以做的不多,除了丟棄你當前正在運行的批量作業,並且只是不知道未完成的項目。

解決方案是使用持久消息隊列來記錄任何待處理的工作。如果服務器關閉,則當前正在處理的消息不應被確認,因此他們有機會在下次啓動服務器時重新處理。