【问题标题】:Controlling CDI Startup inside EJB 3.1在 EJB 3.1 中控制 CDI 启动
【发布时间】:2012-12-24 08:36:32
【问题描述】:

我是新来的,也是 CDI 世界的新手,我工作中的第一个任务是找到一种控制 CDI 上传的方法。

我们同时使用EJB 3.1CDI 1.0,因为它们由不同的容器控制,所以我们可以通过使用@Startup@Singleton 注释来控制EJB Managed Beans 的启动时间和顺序。

但是我在课堂上声明的 @Inject CDI bean 将变为 null,因为 CDI 容器尚未启动。

我已经尝试了几天来寻找解决方案,但我发现 here 的那个没有用(仍然为空)。

我们正在使用 Java EE 6 并在 WebSphere Application Server 8 上运行应用程序。

拜托,如果你能帮我找到一种方法来控制内部的 CDI 上传,而不管 EJB 是什么?

这是它的示例代码:

import javax.annotation.PostConstruct;
import javax.ejb.Singleton;
import javax.ejb.Startup;

@Singleton
@Startup
public class BaseStartupLoader{


/**
 * Default constructor. 
 */
@Inject @MyStartup
BaseStartUp myStartup;

private static Logger m_logger = LoggerFactory.getLogger(BaseStartupLoader.class);
public BaseStartupLoader() {

}

@PostConstruct
public void init(){

    String applicationName = null;

    try {

            applicationName = myStartup.getClass().getName();
            myStartup.load();

    } catch (IllegalAccessException e) {
        m_logger.error("Faild to load data into preload system. "+e);               
    } catch (InstantiationException e) {
        m_logger.error("Faild to load data into preload system. "+e);               
    } catch (ClassNotFoundException e) {
        m_logger.error("Faild to load data into preload system - Class "+ applicationName + "Not found. "+e);               
    }
  }
}

这是 BaseStartup 接口:

public interface BaseStartUp {
public void load() throws IllegalAccessException, InstantiationException, ClassNotFoundException;
}  

限定符和实现:

@Retention(RetentionPolicy.RUNTIME)
@Target ({ElementType.PARAMETER, ElementType.FIELD, ElementType.TYPE, ElementType.METHOD})
@Qualifier 
@Dependent
public @interface MyStartup {   
}


@MyStartup
public class MyStartUpLoader implements BaseStartUp {

    @Inject
    SomeConfigLoader config;

    @Override
    public void load() throws IllegalAccessException, InstantiationException, ClassNotFoundException {
    conifg.init();      
}   
}

【问题讨论】:

  • 您能添加一些示例代码吗?
  • 我已经用代码示例编辑了问题。
  • 只是想知道,但“受控上传”与问题的其余部分有什么关系?
  • 我正在尝试控制 CDI 的起点。我用上传这个词来描述容器在服务器启动时的起点。

标签: java jakarta-ee java-ee-6 cdi ejb-3.1


【解决方案1】:

经过大量研究后,我从 IBM 的人那里得到了一些帮助,因为我们正在使用 WebSphere Application Server,所以我可以添加一个 JVM 属性,名为:

"com.ibm.ws.cdi.immediate.ejb.start" = true

到管理控制台中的 WAS,他将确保一旦我在 @Startup bean 中访问 EJB @PostConstruct 方法,我创建的 CDI 容器将已经启动并运行并且已经注入。

有效!!

这是 IBM 站点中问题和解决方案的链接:

http://www-01.ibm.com/support/docview.wss?uid=swg1PM62774

【讨论】:

  • 请注意,这会改变类加载器,导致 JPA 提供程序从 Eclipse Link 更改为 OpenJPA(在 WebSphere 8.5.5.4 下找到),
【解决方案2】:

可能会仔细检查 CDI 是否已在应用程序的所有需要​​的位置启用。尝试将此代码添加到BaseStartupLoader 作为实验:

@Singleton
@Startup
public class BaseStartupLoader {

    @Inject @MyStartup
    BaseStartUp myStartup;

    @Inject
    private InjectionTest test;


    public static class InjectionTest {}
}

如果test 变量在@PostConstruct 中出现为空,则可能在声明BaseStartupLoader 的jar 中未启用CDI。

如果说,例如,BaseStartupLoader 在名为 orange.jar 的 jar 中声明,MyStartUpLoader 在名为 yellow.jar 的 jar 中声明,那么这两个文件都必须存在:

  • orange.jar!/META-INF/beans.xml
  • yellow.jar!/META-INF/beans.xml

如果通过META-INF/beans.xml 在两个 jar 中正确启用 CDI,则这是容器中的错误。在调用@PostConstruct 之前,需要完成所有@Inject 点(对于启用CDI 的jar)。无论是否使用 @Startup 并且其中一个 bean 恰好是 EJB,这都是正确的。

【讨论】:

  • 静态内部类注入是一个巧妙的技巧!感谢分享这个技巧。
  • 感谢您的快速响应,我已经完成了您的测试,并且确实该变量在 @PostConstruct 中显示为 null,此外,在 META-INF/beans 中存在更多的 jars 文件。 xml,但真正的问题是 CDI 容器尚未初始化,而 EBJ 容器已经启动,我在 web 上找到了一种解决方案 - 使用加载时启动 Servlet 强制在 EJB 之前启动 CDI 容器。但这个解决方案对我们不利(我们不希望在后端使用 WAR 文件。如果有人有任何其他想法,我愿意接受建议......
【解决方案3】:

看看 DeltaSpike。有一个 CDI 控制模块应该可以满足您的需求。我相信 Java EE 7 也应该解决这个问题。

【讨论】:

  • 你没有看错,我发现这个问题会在 CDI 1.1 Release 中解决,但我还是很惊讶地看到没有积极的解决方案(除了 Servlet load-on-启动一)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-19
  • 2011-08-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多