在战争包装和包装成EAR->罐子当有状态会话bean意外的行为(Stateful sessio

2019-10-19 07:12发布

我是新来的EJB。 我写了作用域@SessionScoped有状态会话bean。 然后,我将注入到EJB我的servlet。

@Local
@SessionScoped
@Statueful
public class CartServiceImpl implements CartService {

    private int i = 0;

    public int getI() {
        return i++;
    }
}

在我的servlet

@Inject
private CartService cartService;
.
.
.
out.print(cartService.getI());

然后我打开两个浏览器(IE,FF),并击中这个servlet。 在IE中我看到输出从0开始到n。 在Firefox中也看到我的输出从0开始到n。

然后,我创建创建具有瓶和战争的耳朵。 罐子包含了所有的EJB。 战争包含的servlet。

这是我如何注入EJB到servlet

@Resource(lookup = "java:app/ejb-beginner-ejb/CartServiceImpl")
private CartService cartService; 

然后我试图请求来自IE和FF相同的servlet和我得到意想不到的输出。

输出是如下

在IE中我请求第一次,我得到0作为输出。 然后我刷新页面,我得到1作为输出。 然后,我搬到FF,发送请求的第一时间,我得到2作为输出,而不是0。然后我移动到IE和刷新页面,我得到3输出,而不是2。

我的理解是应用程序服务器创建状态EJB的只有一个实例。 我怎样才能解决这个问题?

是什么在战争中包装EJB和一个jar模块分开包装它们之间的区别?

Answer 1:

我认为这与事实,@SessionScoped注释,就是要在网络方面只用来做什么,否则,就像你的第二个案例,它没有任何意义,你应该认为它会被忽略,你的状态EJB会像普通旧有状态EJB,并且在一般情况下,你不应该注入有状态的资源投入到那些无国籍因为通常的结果是不可预测的,依赖于容器实现。 话虽如此,小服务器是无状态的部件,并且不需要通过容器规范来创建每个请求或会话的一个实例,从在Servlet 3.0规范(秒2.2。):

对于在分布式环境中(默认值)不举办一个servlet,servlet容器必须采用单次的servlet声明只有一个实例。 然而,用于实现SingleThreadModel接口一个servlet,servlet容器可以实例化的多个实例来处理一个请求重负载和序列化请求发送到特定实例。

但是你应该甚至不应该依赖这样的事实,因为实际上很多容器使用的servlet池来提高性能,而另一方面,有只有一个servlet实例,当你仰望或注入有状态EJB为无状态组件是你的责任照顾特定实例的范围,使其能够工作,因为它是应该,在这种情况下,因为你没有控制自己的Servlet实例的实例化,无论你有它在你的EJB实例。

编辑

我会用会在我的web应用程序范围的Bean,但是如果你绝对比你所能使用状态EJB(因为你需要一些他们所提供的服务),在servlet,需要时查找的EJB和它关联到用户的HttpSession使其会话范围,在这种情况下,你应该小心,确保如果会话过期的EJB获取实现会话生命周期监听取出,检查这

你应该考虑其他的含义在这里



文章来源: Stateful session beans unexpected behaviour when packaged in a war and packaged in an ear->jar