将@SessionScoped CDI Bean注入到@Stateless EJB中

5
我希望将一个sessionscoped CDI bean注入到一个stateless EJB中。在访问EJB时,应该使用调用者sessionscope中的正确实例sessionscoped cdi bean。我知道可以通过stateful EJB解决这个问题,但是我真的很想知道是否也可以通过CDI来解决。由于EJB和Servlet运行在同一个war中,我认为它们共享同一个线程,容器应该能够找出EJB中正确的sessionscoped bean。
例如:
EJB:
@Stateless
@LocalBean
public class StatelessSessionBean {

    @Inject    
    Instance<SessionData> sessionData;    

    public String testMethod() {
        SessionData bean = sessionData.get();
        String result = "Retrieved bean " + bean + " with UUID "+ bean.uuid + ". Created on: " + new SimpleDateFormat("dd.MM.yyyy HH:mm").format(bean.creationDate);
        return result;
    }
}

CDI Bean:

@SessionScoped
public class SessionData implements Serializable {      

    String uuid;
    Date creationDate;

    public SessionData() {
        uuid = UUID.randomUUID().toString();
        creationDate = new Date();
    }    
}

当我从servlet访问无状态EJB时,我想让testMethod使用与调用者的HTTPSession关联的CDI bean。因此,如果来自不同浏览器/HTTP会话的两个客户端访问Servlet,则它们应该都获得不同的结果字符串。

我需要一个CDI Provider 来代替Instance吗?如果需要,如何为给定的会话生成正确的bean实例? 我考虑过获取BeanManager并搜索SessionData的实例,但我不知道如何获取正确的实例。

非常感谢任何帮助!


你没有告诉我当你尝试运行代码时发生了什么。 - JB Nizet
你正在使用哪个应用服务器或CDI实现?我建议添加一个标签。 - Brett Kail
@bkail 我正在使用Glasfish 4,据我所知这是Weld... 我添加了标签。 - Korgen
@JBNizet 我必须更具体地说明:我得到了一个不同的引用,但始终具有相同的UUID和创建日期...所以我认为代理是不同的,但使用的对象是相同的。 - Korgen
2个回答

5

好的,现在我感觉有点儿愚蠢 :-(

我没有使用getter/setter方法来访问成员变量,而是直接使用了包级私有字段,这样就绕过了代理提供的上下文bean。当我改用getter/setter方法后,它开始按预期工作。


那么,当我们将一个 @SessionScoped 的 CDI bean 注入到 @Stateless EJB bean 中时,如果我们使用 getter 方法访问它们,@Stateless EJB bean 不会混淆、混淆 session-self 参数,对吗? - misman

0

通过客户端代理,将长期存在的bean作用域注入到短期存在的bean作用域中(包括EJB的Dependent作用域)可以直接使用。

请参阅Weld参考手册中的相应章节。


很遗憾,我无法确认这一点...如果我只使用@Inject(而不使用Instance<SessionData>),并从不同的会话(即浏览器)访问它,我会得到一个不同的代理引用,但bean实例仍然保持不变(它具有相同的创建日期和相同的UUID)。 - Korgen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接