5

我刚刚阅读了关于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 文件夹中。

4

1 回答 1

8

摘自Java EE 6 教程并进行了一些修改:

@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 服务

于 2012-09-03T13:14:38.503 回答