在 Singleton 的 PreDestroy 方法中访问无状态 EJB
Posted
技术标签:
【中文标题】在 Singleton 的 PreDestroy 方法中访问无状态 EJB【英文标题】:Accessing stateless EJBs in PreDestroy method of Singleton 【发布时间】:2017-01-09 10:25:09 【问题描述】:我在单例的 preDestroy 方法中访问无状态 EJB 时遇到问题。我需要在数据库表中记录应用程序服务器的关闭。
这就是单例的样子:
@Startup
@Singleton
public class ServerShutdown
@EJB
TableFacade tableFacade;
@PreDestroy
private void shutdown()
TestEntity e = tableFacade.find("test");
//do something
这里是无状态bean的示例代码:
@Stateless
public class TableFacade
...
public TestEntity find(String test)
Query query =
getEntityManager().createNamedQuery("TestEntity.namedQuery");
return (TestEntity) query.getSingleResult();
如果服务器正在关闭,则访问 preDestroy 方法并调用 EJB 方法。但是在调用过程中,服务器似乎强制关闭进程,取消了EJB方法的调用。
我正在使用 Java EE 6、JDK 1.8、EJB 3.1、eclipselink 2.5.2。
提前致谢
【问题讨论】:
Errrr 你的问题是......? 【参考方案1】:@predestroy
应该只做ejb资源清理,比如连接、变量等...
您的问题与事务上下文有关,实际上来自规范:
无状态的 PreDestroy 生命周期回调拦截器方法 和有状态会话 bean 在未指定的事务中执行 上下文。
然后:
例如,在一个数据库中执行数据库操作是错误的 有状态会话 bean 的 PostConstruct 或 PreDestroy 生命周期回调 拦截器方法并假设操作是 客户的交易。 PostConstruct 和 PreDestroy 方法 有状态和无状态会话 bean 不受 事务属性,因为在这些方法中处理回滚 会使会话实例的状态图变得非常复杂。
因此,它并没有被明确禁止,但你会被警告可能会出错。
【讨论】:
谢谢!这解释了很多!【参考方案2】:根据 ejb 3.2 规范,允许单例 bean 在其预销毁方法中访问 ejb。见 4.8.6 节表 3。如果一个单例 bean 需要访问另一个单例 bean,那么它必须使用 @DependsOn 注释声明它的依赖关系。原始海报提供的示例应该可以工作。
【讨论】:
以上是关于在 Singleton 的 PreDestroy 方法中访问无状态 EJB的主要内容,如果未能解决你的问题,请参考以下文章
在 JavaEE 6 的 @PostConstruct 中出现异常后是不是调用了 @PreDestroy?
Spring Boot,Spring Security,会话范围 Bean 的会话超时问题,@PreDestroy