使用EJBContext getContextData - 这样安全吗? [英] Using EJBContext getContextData - is this safe?

查看:163
本文介绍了使用EJBContext getContextData - 这样安全吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我计划使用 EJBContext 将一些属性从应用程序层(特别是消息驱动的bean)传递给无法直接注入的持久性生命周期回调或传递参数(EclipseLink中的会话侦听器,实体生命周期回调等),并且该回调通过JNDI获取 EJBContext

I am planning to use EJBContext to pass some properties around from the application tier (specifically, a message-driven bean) to a persistence lifecycle callback that cannot directly be injected or passed parameters (session listener in EclipseLink, entity lifecycle callback, etc.), and that callback is getting the EJBContext via JNDI.

这似乎有用,但是有没有任何隐藏的陷阱,比如我缺少的线程安全或对象生命周期? (假设传递的属性值是不可变的,如String或Long。)

This appears to work but are there any hidden gotchas, like thread safety or object lifespan that I'm missing? (Assume the property value being passed is immutable like String or Long.)

示例bean代码

@MessageDriven
public class MDB implements MessageListener {
   private @Resource MessageDrivenContext context;

   public void onMessage(Message m) { 
      context.getContextData().put("property", "value");
   }
}

然后使用EJBContext的回调

Then the callback that consumes the EJBContext

public void callback() { 
   InitialContext ic = new InitialContext();
   EJBContext context = (EJBContext) ic.lookup("java:comp/EJBContext");
   String value = (String) context.getContextData().get("property");
} 

我想知道的是,我能确定 contextData 地图内容只对当前的调用/线程可见?换句话说,如果两个线程同时运行回调方法,并且都从JNDI查找 EJBContext ,实际上变得不同 contextData 地图内容?

What I'm wondering is, can I be sure that the contextData map contents are only visible to the current invocation/thread? In other words, if two threads are running the callback method concurrently, and both look up an EJBContext from JNDI, they're actually getting different contextData map contents?

而且,实际上是如何工作的 - 从JNDI查找返回的 EJBContext 实际上是一个包装器对象最终 ThreadLocal 类似的结构?

And, how does that actually work - is the EJBContext returned from the JNDI lookup really a wrapper object around a ThreadLocal-like structure ultimately?

推荐答案

我认为一般来说合同该方法的目的是启用拦截器+ webservice上下文和bean之间的通信。因此,只要没有创建新的调用上下文,所有代码都可以使用上下文。因此它应该绝对是线程安全的。

I think in general the contract of the method is to enable the communication between interceptors + webservice contexts and beans. So the context should be available to all code, as long as no new invocation context is created. As such it should be absolutely thread-safe.

EJB 3.1规范的第12.6节说明如下:

Section 12.6 of the EJB 3.1 spec says the following:


InvocationContext对象提供的元数据使
拦截器方法能够控制调用链的行为。
上下文数据在单独的业务方法
调用或生命周期回调事件中不可共享。如果由于在Web服务端点上调用而调用拦截器
,则getContextData返回的映射
将是JAX-WS MessageContext

The InvocationContext object provides metadata that enables interceptor methods to control the behavior of the invocation chain. The contextual data is not sharable across separate business method invocations or lifecycle callback events. If interceptors are invoked as a result of the invocation on a web service endpoint, the map returned by getContextData will be the JAX-WS MessageContext

此外,getContextData方法在4.3.3中描述:

Furthermore, the getContextData method is described in 4.3.3:


getContextData方法启用业务方法,生命周期回调方法或超时方法来检索与其调用相关的任何拦截器/ webservices上下文。

The getContextData method enables a business method, lifecycle callback method, or timeout method to retrieve any interceptor/webservices context associated with its invocation.

在实际实现方面,JBoss AS执行以下操作:

In terms of actual implementation, JBoss AS does the following:

public Map<String, Object> getContextData() {
    return CurrentInvocationContext.get().getContextData();
}

CurrentInvocationContext 使用基于线程本地链表以弹出并推送当前的调用上下文。

Where the CurrentInvocationContext uses a stack based on a thread-local linked list to pop and push the current invocation context.

参见 org.jboss.ejb3.context.CurrentInvocationContext 。调用上下文只是懒惰地创建一个简单的 HashMap ,就像在 org。 jboss.ejb3.interceptor.InvocationContextImpl

See org.jboss.ejb3.context.CurrentInvocationContext. The invocation context just lazily creates a simple HashMap, as is done in org.jboss.ejb3.interceptor.InvocationContextImpl

Glassfish做了类似的事情。它还获取调用,并执行此操作来自调用管理器,使用基于线程局部数组列表再次弹出并推送这些调用上下文。

Glassfish does something similar. It also gets an invocation, and does this from an invocation manager, which also uses a stack based on a thread-local array list to pop and push these invocation contexts again.

GlassFish实现的JavaDoc在这里特别有趣:

The JavaDoc for the GlassFish implementation is especially interesting here:


这个TLS变量存储一个ArrayList。 ArrayList包含
ComponentInvocation对象,它们表示此线程上的调用堆栈
。对ArrayList的访问不需要同步
,因为每个线程都有自己的ArrayList。

This TLS variable stores an ArrayList. The ArrayList contains ComponentInvocation objects which represent the stack of invocations on this thread. Accesses to the ArrayList dont need to be synchronized because each thread has its own ArrayList.

就像在JBoss AS中一样, GlassFish懒得创建一个简单的 HashMap ,在本例中是 com.sun.ejb.EjbInvocation 。对GlassFish案例感兴趣的是,Web服务连接更容易在源中发现。

Just as in JBoss AS, GlassFish too lazily creates a simple HashMap, in this case in com.sun.ejb.EjbInvocation. Interesting in the GlassFish case is that the webservice connection is easier to spot in the source.

这篇关于使用EJBContext getContextData - 这样安全吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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