Spring / Hibernate在关闭EntityManagerFactory之前添加了一个关闭钩子 [英] Spring/Hibernate adding a shutdown hook running prior to closing the EntityManagerFactory

查看:184
本文介绍了Spring / Hibernate在关闭EntityManagerFactory之前添加了一个关闭钩子的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我关闭我的服务器时,我有一些工作正在填充下载和填充我想要允许优雅地完成的数据。



我试图添加一个Runtime.getRuntime()。addShutDownHook()但这似乎是在Entitymanager已经关闭之后运行的,因为在运行之前异常开始涌入。



然后我尝试添加它以实现ServletContextListener和

  @Override 
public void contextDestroyed(ServletContextEvent servletContextEvent)

在关闭钩子之前运行但仍然在实体经理已经关闭之后。



有没有办法在entitymanager关闭之前运行一些逻辑?



我正在使用

注入entitymanager

  @PersistenceContext(unitName = PERSISTENCE_UNIT)
私有EntityManager entityManager;

使用



<$ p $创建EntitymanagerFactory p> @Configuration

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

当实体管理员关闭时,我怎样才能正确收听,所以我可以先让待处理的工作完成?



我在Java EE上使用Spring,Hibernate,JPA和Web模块。



产生的异常是:

  java.lang.IllegalStateException :EntityManagerFactory已关闭
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.i nvoke(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)


解决方案

这是 EntityManagerFactory 当它被关闭时Spring应用程序上下文被破坏。



根据您记录的异常,主运行线程检测到应用程序销毁事件和 Spring shutdownHook 传播毁灭ev ent到所有已注册的bean,包含EntityManagerFactory



您可能有一个具有一些工作线程的批处理作业,不要监听应用程序销毁事件,因此他们继续执行,因此尝试使用关闭的 EntityManagerFactory EntityManager c>。



因为应用程序上下文被销毁,所以不仅仅是 EntityManagerFactory 已关闭,而是 TransactionManager 以及 DataSource 。这就是为什么除了丢弃当前正在运行的批处理作业并且只是未确认
未完成的项目之外,你无能为力。



解决方案是使用用于记录任何待处理工作的持久消息队列。如果服务器已关闭,则不应确认当前正在处理的消息,因此下次启动服务器时它们有机会进行重新处理。


When I close down my server, I have jobs that are populating downloading and populating data that I would like to allow to finish gracefully.

I tried to add a Runtime.getRuntime().addShutDownHook() but this seems to run after the Entitymanager is already closed, as exception starts pouring in before that gets ran.

Then I tried to add it to implement a ServletContextListener and

@Override
public void contextDestroyed(ServletContextEvent servletContextEvent)

which ran before the shutdown hook but still after the entitymanager had already closed.

Is there a way to run some logic prior to the entitymanager shutting down?

I am injecting the entitymanager using

@PersistenceContext(unitName = PERSISTENCE_UNIT)
private EntityManager entityManager;

The EntitymanagerFactory is created using

@Configuration 

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

How can I properly listen to when the entitymanager gets shut down, so I can allow pending work to complete first?

I am using Spring, Hibernate, JPA on Java EE with a web module.

The resulting exception is this:

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)

解决方案

It's the EntityManagerFactory that get's closed when the Spring application context is destroyed.

According to your logged exception, the main running thread has detected the application destroy event and the Spring shutdownHook propagates the destroy event to all registered beans, EntityManagerFactory included.

You probably have a batch job that has some worker threads, that don't listen to the application destroy event and therefore they continue to execute, therefore trying to create an EntityManager using a closed EntityManagerFactory.

Because the application context is destroyed, it's not just the EntityManagerFactory that is closed, but the TransactionManager and the DataSource as well. That's why there's not much you can do about it, other than discarding your current running batch jobs and simply unacknowledge the unfinished items.

The solution is to use a persisted message queue for recording any pending work. If the server is closed, the currently processing messages shouldn't be acknowledged and so they get a chance to be reprocessed the next time you start your server.

这篇关于Spring / Hibernate在关闭EntityManagerFactory之前添加了一个关闭钩子的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆