【问题标题】:Java EE 6: controlling startup of managed beans with dependencies: CDI, EJBJava EE 6:使用依赖项控制托管 bean 的启动:CDI、EJB
【发布时间】:2012-09-02 11:08:36
【问题描述】:

我刚刚在Java EE 6 @javax.annotation.ManagedBean vs. @javax.inject.Named vs. @javax.faces.ManagedBean 上阅读了关于各种托管 bean 及其关系的非常好的解释,当我在应用程序中遇到一个烦人的问题时,我想知道是否可以控制或影响 bean 的方式和时间开始。

在我的 Java EE 应用程序中,我使用 EJB、CDI 和 JSF2 作为视图技术。通过 SPI 启动来自第三方的服务,并配置一个作业执行器来启动作业并处理其他与计时器相关的内容。当作业执行器完成其引导时,会立即执行一项作业。该作业使用 CDI 注入来访问某些 bean,其中一个 bean 使用 EJB。

现在的问题是大多数时间 Java EE 6 服务器 (JBoss 7.1.1) 启动 EJB 仍然不可用,然后作业尝试访问它。抛出异常并且作业失败,并且构建服务以停用该失败的作业。好吧,停用失败的工作似乎还不错。让作业重新启动和运行的唯一解决方案是取消部署并再次重新部署。不幸的是,这是一项手动任务,无法以编程方式完成。

而且,让事情变得糟糕:在极少数情况下,这不会发生。

所以,我现在的问题是:我能否以某种方式控制 EJB 和 CDI bean 的初始化和部署,以便我可以确保在初始化 CDI bean 之前初始化所有 EJB bean?

我在 EARs application.xml 中将 initialize-in-order 设置为 true 并设置 EJB 的顺序,以便它们按照我需要的方式进行初始化(EJB 核心,然后是 EJB 业务,然后是 WAR),但是基于 CDI 的服务作为 JAR 放置在 lib 文件夹中。

【问题讨论】:

  • 您是否尝试过使用 CDI 的Events 功能?
  • 例如在 EJB @PostConstruct 中触发一个事件,您的服务会观察到该事件。
  • @tair no.我不知道我可以为自己触发 CDI 事件 :) 你的意思是我可以从服务所依赖的所有 EJB 触发事件然后对其采取行动?例如阻止或释放作业?
  • 是的。另一种解决方案是创建一个@Startup MyServiceEjb,其中@DependsOn 是运行服务所需的所有EJB。
  • 如何自动启动 CDI bean?

标签: ejb-3.0 java-ee-6 cdi


【解决方案1】:

摘自Java EE 6 Tutorial,稍作修改:

@Singleton
@Startup
public class BeanA { ... }

@Qualifier
@Target({FIELD, PARAMETER})
@Retention(RUNTIME)
public @interface EjbStarted {}

@Singleton
@Startup
@DependsOn("BeanA", "BeanB", "BeanC")
public class LastBean {
    @Inject @EjbStarted Event<String> event;

    @PostConstruct
    public void startService() {
        // At this moment PrimaryBean is ready for use
        event.fire("LastBean");
    }
}

public class CDIService {
    public void start(@Observes @EjbStarted String name) {
        if("LastBean".equals(name)) {
            startService();
        }
    }
}

更新:在考虑这个问题时,我不知何故忘记了你想要 CDI bean 中的初始化顺序,所以答案有点脱离上下文,对此感到抱歉:)

更新 2:添加了如何在 EJB 之后启动 CDI 服务

【讨论】:

  • 没问题,我从你的回答中了解到 DependsOn 的东西 :) 好吧,最初的问题是,由作业调度程序启动的作业启动了在 BPMN2 流程引擎中运行的流程实例,并且那里的任务使用 EJB。我的问题是,当 EJB 还没有到位时,流程实例就被执行了。也许如果我创建一个依赖于所需 EJB 的 EJB,然后我检查该 EJB 是否可用?我可以通过 JNDI 进行此检查吗?然后我可以在我的流程定义中添加一个任务,该任务执行此检查并正常退出。
  • 我已经用一个牵强的 CDI 事件示例更新了答案,只是为了演示事件功能。一种更简单的方法是在CDIService 中只使用@Inject LastBean@PostConstruct startService()——这只是定义启动依赖项的另一种方法
猜你喜欢
  • 1970-01-01
  • 2018-06-22
  • 1970-01-01
  • 2012-06-22
  • 1970-01-01
  • 2013-06-30
  • 1970-01-01
  • 2015-07-29
  • 1970-01-01
相关资源
最近更新 更多