我们希望在请求或事务结束时执行某些任务。更具体地说,我们需要在该请求期间收集一些数据,最后我们使用该数据进行一些自动数据库更新。
这个过程应尽可能透明,即需要这个过程的EJB用户不必担心这一点。
此外,我们无法控制确切的调用堆栈,因为该进程有多个入口点。
为了实现我们的目标,我们目前正在考虑以下概念:
到目前为止,我们设法启动并运行第1步和第2步。
然而,问题是第3步:
正如我已经说过的,该流程有多个入口点(源自Web请求,预定作业或远程调用),因此我们考虑了以下方法:
3A。 CDI扩展扫描所有bean并为每个EJB添加注释。
3B。为添加的注释注册了一个拦截器,因此在每次调用EJB方法时都会调用拦截器。
3c上。第一次调用该拦截器将在调用的方法返回后触发事件。
这就是问题所在(再次在第3步:) :):
拦截器如何知道它是否是第一次调用?
我们想到了以下内容,但到目前为止都没有工作:
我们尚未尝试的另一种选择,但似乎不鼓励:
然而,AFAIK并不能保证请求将完全由同一个线程处理,因此当容器决定切换到另一个线程时,甚至不会调用上下文传播?
所以,感谢所有忍受我的人,并阅读所有冗长的描述。
欢迎任何有关如何解决此问题的想法。
顺便说一下,这里有一些我们正在使用的软件组件/标准(我们无法切换):
更新:
根据您给出的建议,我们提出了以下解决方案:
@Observes(during=BEFORE_COMPLETION)
- 谢谢,@ bkail)到目前为止这仍然有效,但仍有一个问题:
我们还有由CDI管理并自动注册到MBean服务器的MBean。因此,那些MBean可以注入EJB引用。
但是,当我们尝试调用MBean方法,而MBean方法又调用EJB并因此导致上述过程开始时,我们得到ContextNotActiveException
。这表明在JBoss中,执行MBean方法时不会启动请求上下文。
使用JNDI查找来获取服务而不是DI时,这也不起作用。
关于这一点的任何想法?
更新2 :
好吧,好像我们现在正在运行它。基本上我们做了我在上一次更新中所描述的内容,并通过创建我们自己的范围和上下文(在第一次调用EJB方法时激活,并在相应的拦截器完成时停用)解决了上下文不活动的问题。
通常我们应该能够对请求范围做同样的事情(至少如果我们没有错过规范中的任何内容)但是因为JBoss 7.1中存在一个错误,所以当时没有一个活动的请求上下文从MBean或预定作业(执行JNDI查找)调用EJB。
在拦截器中,我们可以尝试获取活动上下文并在失败时激活bean管理器中存在的那些(在这种情况下很可能是EjbRequestContext
)但是尽管我们进行了测试,但我们还是不计算在每种情况下工作。
然而,自定义范围应独立于任何JBoss范围,因此不应干扰此处。
感谢所有回答/评论的人。
所以,这是最后一个问题:我们应该接受哪些答案,因为你们都帮助我们走上了正确的方向? - 我会尝试自己解决这个问题并将这些观点归结为jan - 他得到的最少:)
答案 0 :(得分:4)
在使用@PreDestroy
注释的方法中完成工作。
@Named
@RequestScoped
public class Foo {
@PreDestroy
public void requestDestroyed() {
// Here.
}
}
在容器销毁bean实例之前调用它。
答案 1 :(得分:2)
您正在寻找的是SessionSynchronization。这使得EJB可以与事务生命周期联系起来,并在事务完成时得到通知。
注意,我是关于事务的具体内容,你提到“请求和事务”,我不知道你是否具体指EJB事务或与你的应用程序绑定的东西。
但我在谈论EJB Transactions。
缺点是它只在调用特定EJB时调用,而不是在一般情况下调用“所有”事务。但无论如何,这可能是合适的。
最后,在这些临时回调区域要小心 - 在这些生命周期方法中,事务发生时我发生了奇怪的事情。最后,最终将内容放入一个本地的,基于内存的队列,另一个线程收集到JMS或其他任何东西。缺点是它们与手头的交易挂钩,其中的好处是它们确实有效。
答案 2 :(得分:1)
Phew,这是一个复杂的场景:)
从我如何理解你到目前为止所尝试的内容来看,你对CDI技术非常了解 - 你没有什么大不了的。
我会说你应该能够在入口点激活对话上下文(你可能已经看过the relevant documentaton?)并在整个处理过程中使用它。考虑实施自己的范围实际上是值得的。我曾经在远程相关的场景中做过一次,我们无法判断我们是否已经被HTTP请求或EJB-remoting调用。
但说实话,这一切都太复杂了。这是一个相当脆弱的拦截器构造,通过事件来互相通知,这些事件似乎都很容易打破。
还有其他方法可以更好地满足您的需求吗?例如。您可能尝试挂钩事务管理本身并从那里执行数据累积?