当前位置: 首页 > 面试题库 >

使用EJBContext getContextData-这样安全吗?

王宏深
2023-03-14
问题内容

我打算用来EJBContext将一些属性从应用程序层(特别是消息驱动的Bean)传递到不能直接注入或传递参数的持久性生命周期回调(EclipseLink中的会话侦听器,实体生命周期回调等),并且该回调EJBContext通过JNDI
获取。

这似乎可以正常工作,但是我是否缺少任何隐藏的陷阱,例如线程安全性或对象寿命?(假设要传递的属性值是不变的,如String或Long。)

样本豆代码

@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方法,并且都EJBContext从JNDI
查找一个,那么它们实际上是在获取不同的contextData映射内容吗?

而且,这实际上是如何工作的- EJBContext从JNDI查找返回的结果ThreadLocal最终是否真的是围绕类结构的包装对象?


问题答案:

我认为一般而言,该方法的约定是启用拦截器+ Web服务上下文与Bean之间的通信。因此, 只要没有创建新的调用上下文
,该上下文应可用于所有代码。因此,它应该绝对是线程安全的。

EJB 3.1规范的第12.6节指出:

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

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

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

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

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

其中CurrentInvocationContext使用基于线程本地链接列表的堆栈来弹出并推送当前调用上下文。

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

Glassfish做类似的事情。它还从调用管理器获得一个调用,该调用管理器还使用基于线程本地数组列表的堆栈来再次弹出并推送这些调用上下文。

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

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

就像在JBoss
AS中一样,GlassFish也懒洋洋地HashMap在com.sun.ejb.EjbInvocation中创建了一个简单的例子。在GlassFish案例中,有趣的是Web服务连接更易于在源中发现。



 类似资料:
  • 生成对称密钥以加密消息时,需要在进程内存中创建一个字节数组。 接下来,您实例化一个对称算法,如AesCryptoServiceProvider。然后通常将key属性设置为内存键。 然后创建一个ICryptoTransform,通常通过调用SymmetricalGorthm。CreateEncryptor()或CreateDecryptor()。您也可以跳过上面的Key属性设置,将Key和IV直接传

  • 问题内容: 我对SQL和锁定策略有疑问。例如,假设我在我的网站上有一个图片计数器。如果我有一个sproc或类似的东西来执行以下语句: 假设在时间t0特定image_id的计数器的值为‘0’。如果两个会话从t0同时开始更新同一个图像计数器s1和s2,则这两个会话都有可能都读取值‘0’,将其增加为‘1’,并且都尝试将计数器更新为‘1 ‘,那么计数器将获得值‘1’而不是‘2’? 最终结果:image_i

  • 问题内容: 根据PHP文档,从mysql表中获取最后插入的ID。 我的问题是,如果我有一个网站每秒向数据库插入2行以上,是否可以使用并获得之前在查询行中引用的正确ID ? 问题答案: 从MySQL手册: 生成的ID在每个连接的服务器中维护。这意味着函数返回给定客户端的值是针对该客户端影响AUTO_INCREMENT列的最新语句生成的第一个AUTO_INCREMENT值。即使其他客户端生成自己的AU

  • 问题内容: 使用HttpURLConnection时,如果我们不“获取”并使用它,是否需要关闭InputStream? 即安全吗? 其次, 在完全读取所有内容之前 关闭InputStream是否安全? 是否存在使基础套接字处于ESTABLISHED或CLOSE_WAIT状态的风险? 问题答案: 在读取所有内容之前关闭InputStream是否安全? 您需要先关闭输入流中的所有数据,然后再关闭它,以

  • 我的工作笔记本电脑运行LinuxMint作为基本操作系统,加上Virtualbox来运行Windows 7,这是实际的工作环境,通常加上一个额外的Virtualbox VM来运行不同的Windows安装,我在其中做我的客户机项目工作(我每个客户机有一个VM,以避免弄乱我的主操作系统)。 但我想知道,在客户项目中使用Docker是否可行和有益?也就是说,我想保留LinuxMint(以保持我的理智),

  • 下面是在动作2中使用来自C++并发的锁的线程安全列表的示例源代码。 我理解这段代码的工作原理。但我不认为这个代码是完美的。我在这三个地方做了记号。 (1)析构函数中的remove_if确有必要?节点中的每个数据都使用智能指针。所以我不认为析构函数必须移除列表中的元素。你的意见呢? (2)即使使用remove_if,lambda函数的参数[](节点const&){...}看起来怪怪的。我认为lamb