【问题标题】:Stateful session beans unexpected behaviour when packaged in a war and packaged in an ear->jar有状态会话 bean 打包在 war 中并打包在 ear->jar 中时的意外行为
【发布时间】:2014-02-23 21:17:08
【问题描述】:

我是 ejbs 的新手。我写了一个作用域为@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 的输出。

然后我创建了一个耳朵,它有一个罐子和一个战争。 jar 包含所有 ejb。 war 包含 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 的实例。我该如何解决这个问题?

war中打包ejb和单独打包到jar模块有什么区别?

【问题讨论】:

  • 有趣。显然,当您将其打包为战争的一部分时,会话范围的字面意思是 HTTP 会话的一部分,而当您将其打包在 EJB 模块中时,这当然不再与任何 HTTP 会话相关,并且显然是基于 IP 进行管理的的客户。无论如何,这就是我从您的测试结果中得出的结论。有状态的 bean 对我来说是神秘的野兽。
  • 好的。在这种情况下,有状态会话 bean 什么时候到期?有状态会话bean与http会话绑定时,客户端一终止就过期(例如关闭浏览器) 万一http会话没有绑定,有状态会话bean使用客户端的ip,什么时候删除/终止?是客户端更改他的IP时吗?是客户端重启机器的时候吗?
  • 如果你发现了,请告诉我!

标签: java jakarta-ee ejb ejb-3.0 stateful-session-bean


【解决方案1】:

我认为这与 @SessionScoped 注释仅用于 Web 上下文这一事实有关,否则,就像您的第二种情况一样,它没有意义,您应该假设它会被忽略,您的有状态 ejb 将表现得像旧的常规有状态 ejb,一般来说,您不应该将有状态资源注入无状态资源,因为通常结果是不可预测的并且取决于容器实现。话虽如此,servlet 是无状态组件,并且规范不要求容器根据 Servlet 3.0 规范(第 2.2 节)为每个请求或会话创建一个实例:

对于不在分布式环境中托管的 servlet(默认),servlet 每个 servlet 声明容器必须只使用一个实例。但是,对于 servlet 实现 SingleThreadModel 接口,servlet 容器可以 实例化多个实例以处理繁重的请求负载并序列化请求 到一个特定的实例。

但是,您甚至不应该依赖只有一个 servlet 实例这一事实,因为事实上许多容器使用 servlet 池来提高性能,另一方面,当您在无状态组件中查找或注入有状态 EJB 时,它是您有责任处理该特定实例的范围,以便它可以按预期工作,在这种情况下,因为您无法控制 servlet 实例的实例化,也无法控制您的 ejb 实例。

编辑

我会在我的 Web 应用程序中使用会话范围的 bean,但是如果您肯定必须使用有状态 EJB(因为您需要它们提供的一些服务),那么您可以在 servlet 中在需要时查找 ejb 并关联它给用户 HttpSession 以使其成为会话范围,在这种情况下,您应该小心并确保如果会话过期,则通过实现会话生命周期侦听器来删除 ejb,检查this

您应该考虑的其他影响here

【讨论】:

  • 从您的解释中我只了解很少。我的理解是,永远不应该将有状态 bean 注入 servlet/无状态 bean。那么我应该怎么做才能使用有状态的bean呢?我应该在 servlet 的 doGet 或 doPost 方法中创建有状态 bean 的实例吗?我的理解对吗?
  • 对不起,我还是听不懂。您能否通过查找 ejb 并与用户 HttpSession 关联来提供有关您的意思的代码 sn-p。
  • 我在我的 servlet 中注入了一个 SFSB 并打开了 2 个浏览器,我可以看到两个不同的会话。我的 SFSB 是会话范围的。它工作正常。我用jboss来测试。
猜你喜欢
  • 2011-05-25
  • 2017-08-27
  • 2013-10-06
  • 2015-12-15
  • 1970-01-01
  • 1970-01-01
  • 2011-10-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多