Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/362.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用EJBContext getContextData-安全吗?_Java_Jakarta Ee_Java Ee 6_Ejb 3.1 - Fatal编程技术网

Java 使用EJBContext getContextData-安全吗?

Java 使用EJBContext getContextData-安全吗?,java,jakarta-ee,java-ee-6,ejb-3.1,Java,Jakarta Ee,Java Ee 6,Ejb 3.1,我计划使用EJBContext将一些属性从应用层(特别是消息驱动的bean)传递给无法直接注入或传递参数的持久性生命周期回调(EclipseLink中的会话侦听器、实体生命周期回调等),该回调通过JNDI获取EJBContext 这似乎是可行的,但是否有任何隐藏的陷阱,如线程安全或对象寿命,我错过了?(假设传递的属性值是不可变的,如字符串或Long。) 示例bean代码 @MessageDriven public class MDB implements MessageListener {

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

这似乎是可行的,但是否有任何隐藏的陷阱,如线程安全或对象寿命,我错过了?(假设传递的属性值是不可变的,如字符串或Long。)

示例bean代码

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

   public void onMessage(Message m) { 
      context.getContextData().put("property", "value");
   }
}
然后是使用EJBContext的回调

public void callback() { 
   InitialContext ic = new InitialContext();
   EJBContext context = (EJBContext) ic.lookup("java:comp/EJBContext");
   String value = (String) context.getContextData().get("property");
} 
我想知道的是,我能否确保
contextData
映射内容只对当前调用/线程可见?换句话说,如果两个线程同时运行
callback
方法,并且都从JNDI中查找
EJBContext
,那么它们实际上得到的
contextData
映射内容是不同的吗


那么,这实际上是如何工作的呢?从JNDI查找返回的
EJBContext
真的是一个围绕
ThreadLocal
-样结构的包装器对象吗?

关于
EJBContext
的问题,我无法直接帮助您,自从在JEE6中添加了
getContextData
方法以来,关于它的文档仍然不多

但是,还有另一种方法可以使用在EJB、拦截器和生命周期回调之间传递上下文数据。概念和示例代码可以在本文中找到


javax.transaction.TransactionSynchronizationRegistry
持有类似于映射的结构,可用于在事务内传递状态。从旧的J2EE1.4开始,它就可以完美地工作,并且与线程无关


由于拦截器与ServiceFacade在同一事务中执行,因此甚至可以在
@AroundInvoke
方法中设置状态。
TransactionSynchronizationRegistry
(TSR)可以直接注入到拦截器中


那里的示例使用
@Resource
注入来获取
事务同步注册表
,但也可以从
初始上下文中查找它,如下所示:

public static TransactionSynchronizationRegistry lookupTransactionSynchronizationRegistry() throws NamingException {
    InitialContext ic = new InitialContext();
    return (TransactionSynchronizationRegistry)ic.lookup("java:comp/TransactionSynchronizationRegistry");
}

我认为,一般来说,该方法的契约是支持拦截器+Web服务上下文和bean之间的通信。因此,只要不创建新的调用上下文,所有代码都应该可以使用上下文。因此,它应该是绝对线程安全的

EJB3.1规范的第12.6节说明了以下内容:

public Map<String, Object> getContextData() {
    return CurrentInvocationContext.get().getContextData();
}
InvocationContext对象提供元数据,该元数据支持 拦截器方法来控制调用链的行为。 上下文数据不能跨单独的业务方法共享 调用或生命周期回调事件。如果调用了拦截器 作为对web服务端点调用的结果,映射 getContextData返回的将是JAX-WS MessageContext

此外,getContextData方法如4.3.3所述:

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

在实际实现方面,JBoss做了如下工作:

public Map<String, Object> getContextData() {
    return CurrentInvocationContext.get().getContextData();
}
公共映射getContextData(){ 返回CurrentInvocationContext.get().getContextData(); }
其中,
CurrentInvocationContext
使用基于的堆栈来弹出和推送当前调用上下文

看。调用上下文只是懒洋洋地创建一个简单的
HashMap
,如中所述

玻璃鱼也有类似的作用。它也会这样做,它还使用一个基于的堆栈来再次弹出和推送这些调用上下文

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

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


正如在JBoss as中一样,GlassFish也懒散地创建了一个简单的
HashMap
,在本例中为。GlassFish案例中有趣的是,webservice连接更容易在源代码中找到。

好建议。我在
EJBContext
中使用的模式几乎是相同的-在一个地方注入
@Resource
,将对象放在地图中,然后在其他地方的JNDI中查找。因此,问题是
EJBContext
对象是否也像
TransactionSynchronizationRegistry
TransactionSynchronizationRegistry一样是线程独立的,它有一个限制:它总是需要一个事务,但在某些情况下需要在没有事务的情况下传播信息