【问题标题】:EJB3 how to make sure things happen before a bean get deletedEJB3如何确保在删除bean之前发生事情
【发布时间】:2011-07-18 08:45:03
【问题描述】:

假设我让我的客户使用 Stateful Session Bean 预订飞机上的座位。如果客户端显式调用了我的 Remove 方法,他的所有保留都将被取消,然后 bean 将被删除。

但是,如果客户端空闲一段时间并且 Bean 被钝化,如果 Bean 在被钝化时超时,它将被删除而不调用我的任何函数。因此,如果有人能告诉我如何确保在删除 bean 时取消预订,我将不胜感激。如果我使用@PreDestroy注解,会解决这个问题吗?

最好的问候, 詹姆斯·特兰

【问题讨论】:

  • 好吧,在我看来@PreDestroy 不会解决这个问题。假设 A 的状态被钝化,而 B 当前在 Stateful bean 上处于活动状态,如果调用 @PreDestroy 函数,则只会取消 B 的保留。我说的对吗?
  • 不是真的,每个客户端总是有一个(有状态的)bean 实例。

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


【解决方案1】:

@PreDestroy 方法很可能不会被调用。 EJB 3.1 规范明确指出:

4.6.3 错过的 PreDestroy 调用

Bean Provider 不能假设容器总是调用 PreDestroy 生命周期回调拦截器方法(或 ejbRemove 方法)用于会话 bean 实例。以下情况会导致 PreDestroy 生命周期回调拦截器方法不是 调用实例:

• EJB 容器崩溃。

• 从实例的方法向容器抛出的系统异常。

当实例处于被动状态时客户端不活动超时。 超时由部署程序以特定于 EJB 容器实现的方式指定。

该规范还详细说明了如果在这种情况下不调用 @PreDestroy 方法,如何移除资源:

例如,如果购物车组件被实现为会话 bean,会话 bean 将购物车内容存储在 数据库,应用程序应该提供一个运行的程序 定期从数据库中删除“废弃”的购物车。

就您而言,这取决于您存储预订状态的方式。如果它们保留在数据库中,那么我建议采用与规范中规定的方法相同的方法。您可以使用 EJB Timer 服务来定期执行此活动,或者使用 Quartz 之类的调度程序。请注意,必须区分不再存在的钝化会话 bean 实例的内容和将再次准备就绪的会话 bean 实例的内容。

【讨论】:

  • 感谢您的详细解答。如果您能帮助我解决另一个小问题,我将不胜感激。如果 bean 在被钝化时被删除,客户端的会话仍然有对被删除 bean 的引用。您能否告诉我如何检测到 bean 已被删除?
  • 您的问题 - Could you please show me how I can detect that the bean has been deleted? 暗示可以检测到,而实际上客户无法检测到。有状态会话 bean 由容器创建和管理。客户端只有一个对它的代理引用。如果您需要处理这种情况,您必须在每次方法调用时捕获可能可能引发NoSuchEJBException 异常,并尝试创建 bean 的新实例。
【解决方案2】:

钝化的 bean 将在超时时被销毁,因此任何带有 @PreDestroy 注释的方法都将执行您正在寻找的操作。

当 A 处于活动状态时,A 的 Stateful bean 实例将不会与 B 共享,直到 A 的实例被销毁。请参阅本文的the diagram 以进一步阅读

【讨论】:

  • 非常感谢。这篇文章真的很有用=)。
【解决方案3】:

是的,应该。带有@PreDestroy 注释的方法将在bean 移除之前被调用(即使我在钝化状态下超时)

【讨论】:

  • 感谢您的回复 =)。我有另一个问题。在《学习 EJB 3.0 编程》一书中,作者写道:“钝化的会话 bean 实例没有被破坏,可以用来服务不同的客户端请求。”这是否意味着 1 个有状态的 bean 可以保存多个客户端的状态(1 个处于活动状态,所有其他处于钝化状态)?因此,当调用 bean @PreDestroy 函数时,它只能对当前活动状态执行操作。我想我在这里有些误解,如果我错了,请纠正我。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多