2012-11-29 65 views
5

我想我在这里有一个基本的理解问题,我希望有人能向我解释这一点。JAVA EE 6共享有状态EJB之间的实例

假设我们有一个状态EJB_A和状态EJB_B和sessionscoped ManagedbeanA:

@Stateful 
@LocalBean 
public class EJB_A { 
} 

@Stateful 
@LocalBean 
public class EJB_B { 
    @EJB 
    EJB_A ejb; 
} 
@ManagedBean 
@SessionScoped 
public class ManagedBeanA { 
    @EJB 
    EJB_A ejb; 
} 

在ManagedBeanA,创建EJB_A。现在,当我使用具有EJB_A作为属性的EJB_B时,在EJB_B中创建了一个新的EJB_A实例。它不是在ManagedBeanA中创建的同一个EJB_A实例。

我不明白,因为我认为有状态EJB的全部意义在于,对于每个客户端,只有一个实例由EJB容器创建并共享和管理。有人可以向我解释这个吗?还请解释我如何才能实现一个EJB的同一个实例被多个其他EJB共享?

谢谢

+0

“现在,当我使用EJB_B“你是什么意思?你是如何验证它不是同一个实例的? –

+0

当我投入EJB_B并查看EJB_A的属性(例如字符串属性)时,EJB_A bean的属性与受管理bean所实例化的EJB_A的属性不同。 – user1727072

+0

你在哪里'instanciate'EJB_B;在另一个ManagedBean或Java客户端(远程查找)中? –

回答

9

是的,你混了不同的概念,不同的APIS太... 我宁愿当你说使用@注入了@EJB并指定注入实例的范围..

@Stateful 
@LocalBean 
public class EJB_A { 
} 

@Stateful 
@LocalBean 
public class EJB_B { 
    @Inject @SessionScoped 
    EJB_A ejb; 
} 
@ManagedBean 
@SessionScoped 
public class ManagedBeanA { 
    @Inject @SessionScoped 
    EJB_A ejb; 
} 
+0

你能解释为什么我应该使用@Inject而不是@EJB? – user1727072

+1

那么,这个主题的深入讨论是: [链接] http://www.seamframework.org/107780.lace 基本上,判别因子是'@ Inject'总是知道的范围注入的对象,并确保注入的实例是一个托管的实例(从而防止令人讨厌的远程bean序列化问题)。 使用@Inject获得一个(有时是代理的)托管对象,使用'@ EJB'获得一个资源,与简单的JNDI查找没多大区别 –

+0

谢谢你为我解释了很多:)! – user1727072

1

我想我混了两件事情 - @SessionScoped和@Stateful。

@Stateful注释并不意味着每个客户端只创建一个实例。这仅仅意味着@ Stateful-EJB只属于一个客户端,而@ Stateless-EJB可以被多个客户端共享。因此@ @ Stateful-EJB具有N:1关系(N @ Stateful-EJB属于正好一个客户端)和@ Stateless-EJB具有N:M关系(N @ Stateless-EJBS属于M个客户端)。这意味着,通过仅对@Stateful EJB使用@ EJB-Annotation,EJB-instance不能被多个其他EJB共享。

另一方面,似乎只有每个客户端创建一次@ Sessionscoped-Managedbean。

我知道了吗?

2

我刚刚做了一些阅读here

的原因是,一个EJB 3.0有状态会话Bean中创建一个新的 豆身份 远程或本地业务接口的结果每个查找()。从查找返回的每个引用指的是不同的有状态会话bean。由呼叫者决定 如何管理对该参考的访问。通常,应用程序将在HttpSession或 应用程序范围(ServletContext)作用域中存储引用以供后续访问。

和:

你的情况不要忘记我们正在处理2种类型的会话:在 会话bean和Web会议。前者确保一旦你请求一个有状态bean,它的身份在该用户会话中保持不变。但是当你使用后者时,你在bean会话顶部的 上有一个Web会话。为了确保您从2个不同的JSP访问同一个bean(或者当您重新加载时),您需要将 bean的标识存储到Web会话作用域中。

所以你其实是对的。当您想要使用您的实例时,您必须使用ManagedBean将其检索到其他位置,因为EJB实例与此会话上下文关联。因此,如果您想简化它并确保每个会话只存在一次EJB,请使用CDI并另外使用@javax.enterprise.context.SessionScoped注释EJB本身;比你可以确定。

+0

非常感谢您的帮助! – user1727072