Java EE 6:使用依赖项控制托管bean的启动:CDI,EJB

Joy*_*ysn 4 cdi ejb-3.0 java-ee-6

我刚刚阅读了各种托管bean及其关于Java EE 6 @ javax.annotation.ManagedBean与@ javax.inject.Named与@ javax.faces.ManagedBean的关系的非常好的解释,因为我面临一个烦人的问题.应用程序我想知道是否可以控制或影响bean的启动方式和方式.

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

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

并且,为了使事情变得糟糕:在极少数情况下,这不会发生.

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

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

Tai*_*air 6

摘自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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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