在EJB方法/ @RequestScoped和@Stateless之间传递状态

时间:2012-01-03 03:00:28

标签: ejb java-ee-6 cdi ejb-3.1

我有一个@RequestScoped CDI bean,我想把它变成一个EJB来获取声明式事务。 (我在EJB 3.1,Java EE 6上)

目前,我在子例程之间传递状态,假设实例仅用于单个请求。如果我现在添加@Stateless,那么假设就会改变。

例如,我想做类似

的事情
@Stateless
@Named
@RequestScoped
public class Foo {
  private String var1; // can't use instance vars in @Stateless?
  private String var2;

  public void transactionForRequest() {
    var1 = value; 
    var2 = value;
    ....
    subroutine();
  }
}

我认为上述方法不起作用 - 这是正确的吗?

我正在考虑两种选择:

  • 使用@Stateful代替@Stateless,以及@Named和@RequestScoped。
  • 保留@Stateless并使用EJBContext.getContextData map替换实例变量。

哪个更好?还有其他一些我没想到的选择吗? (除了等待Java EE 7或切换到Spring。: - ))

3 个答案:

答案 0 :(得分:12)

虽然@Stateless@Singleton@MessageDriven可以通过@Inject注入范围参考,但它们不能 @RequestScoped或任何其他范围。只有@Stateful模型足够灵活,可以支持范围。换句话说,您可以将@Stateful bean类本身注释为@RequestScoped@SessionScoped等。

简单来说,@Stateless@Singleton已经修复了“范围”。 @Singleton基本上是@ApplicationScoped,而@Stateless可能是@InvocationScoped之类的组成范围,如果存在的话。 @MessageDriven bean的生命周期完全取决于驱动它的连接器,因此也不允许具有用户定义的范围。

另见https://stackoverflow.com/a/8720148/190816

答案 1 :(得分:3)

我会选择SFSB而不是SLSB。你想拥有一个状态,所以对我来说这是最重要的信息 - 这是有状态EJB的工作。

此外,我认为EJBContext#getContextData()不会对您有所帮助。据我记忆,它仅在通话期间有效。因此,每次在EJB上调用方法都会创建新的上下文数据映射(至少这是我所期望的。)

答案 2 :(得分:1)

如果您使用无状态bean,则您负责任何状态管理,并且通常使用HttpSessions在Web应用程序层中执行此操作。是的,你不能使用实例变量作为无状态bean。