Java 如何在异步EJB中将数据从EJB拦截器传递到拦截器
我有两个无状态EJB无状态A和无状态B,它们分别有拦截器InterceptorA和InterceptorB。此外,无状态B具有异步方法。大概是这样的:Java 如何在异步EJB中将数据从EJB拦截器传递到拦截器,java,jakarta-ee,asynchronous,ejb,Java,Jakarta Ee,Asynchronous,Ejb,我有两个无状态EJB无状态A和无状态B,它们分别有拦截器InterceptorA和InterceptorB。此外,无状态B具有异步方法。大概是这样的: @Stateless @Interceptors(InterceptorA.class) public class StatelessA{... @Stateless @Asynchronous @Interceptors(InterceptorB.class) public class StatelessB{... @Stateless @
@Stateless
@Interceptors(InterceptorA.class)
public class StatelessA{...
@Stateless
@Asynchronous
@Interceptors(InterceptorB.class)
public class StatelessB{...
@Stateless
@Interceptors(InterceptorA.class)
public class StatelessA{
public void methodA(Object reserved, ...other params )
@Stateless
@Asynchronous
@Interceptors(InterceptorB.class)
public class StatelessB{
public void methodB(Object reserved, ...other params)
在无状态a上调用方法时,它调用多个无状态B方法并返回一个值。
我试图开发2个拦截器来存储无状态B调用的总时间和小计时间,这是拦截器的目标
我需要这样做,以便InterceptorA可以看到InterceptorB数据的详细信息,因此我只在DB中存储一个值,包含(SLSB a的)总时间和(SLSB B的)小计时间
我尝试使用一个ThreadLocal变量(包含一个时间列表,类似long[]),如果无状态B不是异步的,它就可以正常工作。
问题是,当它是异步的时,变量不可用,因为它运行在不同的线程(AFAIK)中
我还尝试注入EJBContext或使用InvocationContext,但都不起作用
有人能告诉我还有什么其他选择吗?
提前感谢。将您需要的信息存储在@Entity对象中,然后使用@PersistenceContext注释将EntityManager注入bean中以持久化并查找数据,这样做有效吗?比如:
@PersistenceContext
EntityManager entityManager;
...
method() {
MyEntityTimer met = new MyEntityTimer(getCurrentTime(), id);
entityManager.persist(met);
}
...
elsewhere:
MyEntityTimer met = entityManager.find(MyEntityTimer.class, id);
以及:
我将用我最后所做的来回答我的问题。 我发现的将变量从拦截器a传递到拦截器B的唯一方法是向EJB a和B添加一个参数,类似这样:
@Stateless
@Interceptors(InterceptorA.class)
public class StatelessA{...
@Stateless
@Asynchronous
@Interceptors(InterceptorB.class)
public class StatelessB{...
@Stateless
@Interceptors(InterceptorA.class)
public class StatelessA{
public void methodA(Object reserved, ...other params )
@Stateless
@Asynchronous
@Interceptors(InterceptorB.class)
public class StatelessB{
public void methodB(Object reserved, ...other params)
这样,在调用InterceptorA时,我将使用需要与InterceptorB共享的数据设置保留参数。
InterceptorB将访问此变量,从参数中获取该变量不会有任何问题
这个解决方案的缺点是需要虚拟参数,以某种方式将EJB与拦截器耦合起来。我反复考虑了这个问题,找到了一个解决方案,它使用安全上下文传递数据。 解决方案涉及使用异步调用中传播的唯一数据,如EJB 3.1中所述: 4.5.4安全性调用方安全主体通过异步方法调用进行传播。呼叫方安全主体传播 异步方法调用的行为与它的行为完全相同 不支持同步会话bean调用 在JBoss中,可以访问安全上下文并使用其中的数据映射将值从InterceptorA传递到InterceptorB,如下所示: 在InterceptorA中:
SecurityContext securityContext = SecurityContextAssociation.getSecurityContext();
securityContext.getData().put("interceptorAData",data);
在拦截器中:
SecurityContext securityContext = SecurityContextAssociation.getSecurityContext();
securityContext.getData().get("interceptorAData");
我对它进行了测试,它在JBossEAP6.1中运行得非常好
此解决方案意味着将拦截器耦合到服务器实现(JBoss AS),但该原理适用于其他服务器。
优点是它将应用程序逻辑与拦截器分离,这是第一个目标。
非常感谢您的评论。谢谢您的回答:)这可能有效,但我如何将“id”值从拦截器传递到拦截器呢?我不想向bean中的方法添加任何新参数..您能创建一个新的类级别变量并添加一个将id从a传递到B的新方法吗?也许在调用B中的第一个方法之前,先调用B.setId(id)。如果不修改ejb,就不可能将id从A传递到B。我找到了一种向EJB添加参数的方法,为拦截器保留一个变量。我将用这个细节来回答这个问题。无论如何谢谢你!我尝试过这个方法,它对我的特殊情况有效,至少在出现任何陷阱之前。。。然而,我所知道的还没有一个浮出水面。。。所以我不妨给wildfly一个+1检查