【问题标题】:Lookup an EJB by local interface in a multi module project在多模块项目中通过本地接口查找 EJB
【发布时间】:2018-01-13 14:37:09
【问题描述】:

我正在尝试通过 ServiceLocator 进行 EJB 查找,而无需硬编码 JNDI 名称,仅使用本地接口名称。问题在于 EJB 分布在其他模块 (JAR) 中。例如,我有这种情况:

项目-xxx

@Stateless
class EjbXBean implements EjbX {

}

由容器向 JNDI 注册:java:global/project-xxx/EjbXBean

项目-yyy

@Stateless
class EjbYBean implements EjbY {

}

由容器向JNDI注册:java:global/project-yyy/EjbYBean

EjbX 和 EjbY 都是@Local。我想让 EJB 只在另一个模块中执行此操作:

EjbX ejbx = ServiceLocator.lookup(EjbX.class);
EjbY ejby = ServiceLocator.lookup(EjbY.class);

但我不知道只有 ServiceLocator 内部的本地接口的模块(project-yyy 或 project-xxx)是什么。我不能只使用带有模块名称的整个 JNDI 名称进行查找:

EjbX ejbx = ServiceLocator.lookup("java:global/project-yyy/EjbXBean");
EjbY ejby = ServiceLocator.lookup("java:global/project-yyy/EjbYBean");

我试图弄清楚在这种情况下什么是最佳做法,因为我不知道硬编码的 JNDI 名称在 JavaEE 世界中是否是一种好的做法。

我使用 OpenEjb 4.7.4 进行开发和集成测试,使用 Wildfly 10.1.0 进行生产。

更新

我可以在 Wildfly 10.1.0 中使用 CDI:

@Override
public Object lookup(Class<?> type, Annotation... annotations) throws NamingException {
    BeanManager manager = CDI.current().getBeanManager();
    Iterator<Bean<?>> beans = manager.getBeans(type, annotations).iterator();

    if (!beans.hasNext()) {
        throw new NamingException("CDI BeanManager cannot find an instance of requested type " + type.getName());
    }
    Bean<?> bean = beans.next();
    CreationalContext<?> ctx = manager.createCreationalContext(bean);
    return manager.getReference(bean, type, ctx);
}

然后调用:

MyClass.lookup(EjbX.class);

但我不想使用 CDI,因为 I had some problems to put this to work 在可嵌入容器 (OpenEJB) 中。

【问题讨论】:

    标签: jakarta-ee ejb jndi service-locator


    【解决方案1】:

    为什么需要不同的模块?多合一 WAR 将允许您只使用 @Inject Beans。 (在每场包含托管 bean 的战争中,您只需要一个 beans.xml

    我不确定命名的标准化是否适用于 openejb 和 wildfly。因为两者都是 ejb 3.1 它应该但是你检查你的名字是否符合标准?过去我在使用队列和主题时遇到过问题。也许jboss naming ejb3.1 可以提供帮助。

    为确保名称可用,或许您应该考虑使用arquillian 进行测试。 但是我会完全摆脱本地 bean 的这个 Namingservice 问题。

    另外,我不会使用 openejb 进行测试。我知道它是可嵌入的,但差异很大。另一个 CDI 容器,可能是 eclipselink 而不是休眠。两者都有很大的不同。我不会对这些进行测试并在wildfly中部署。

    如果您想要基于 Weld 并使用 hibernate 可嵌入的东西,可以考虑 cdi-unitejb-cdi-unit(好吧,这是我的项目,所以我并不完全公正 ;-))

    【讨论】:

    • 嗨!我正在使用 OpenEJB 从另一个未知的 EJB 容器(称为 MyContainer,它使用 Jetty 到 WebApp)进行转换。他也用于开发和 Selenium 测试,设置与此非常相似:tomee.apache.org/…(我在 OpenEJB 和 Jetty 中找到的唯一示例)。我可以使用完整的 JNDI 名称在项目中使用它,但是现在我们正在迁移到 Java8/Wildfly 并且不再起作用,因为 EJB 的查找使用 BeanManager 和 @Local 接口(我将 OpenEJB 更改为 TomEE,用于 CDI )。
    • 您好,如果您尝试仅测试您的 rest-webservice,使用 Weld 有很多不错的替代方案,也许看看 ex7-simplerest。关于查找,我还不明白真正的问题是什么。旧应用程序是如何将这些模块组合在一起的。 JNDI,我想。为什么不能让 CDI 扫描 bean 并自行将所有内容放在一起,而不进行任何查找?
    • 是的,由 JNDI 提供。在新版本中,他们停止使用 JNDI,现在只使用 CDI 来获取 EJB,但我们遇到了一些问题 (stackoverflow.com/q/45538143/2387977),我正在尝试再次使用 JNDI,并将这个 CDI 问题留到未来。您将在另一个 SO 问题中了解整个场景:)
    • 据我所知,您将来需要同时使用这两个版本:openejb 和 Weld(Wildfly)。您决定修复 OpenEjb 版本。但是,如果您最终需要完全切换到 Wildfly,我会避免尝试修复中间步骤引入 tomee 的问题。
    • 你是对的。我正在努力让 CDI 发挥作用,但我也需要一个 B 计划,因为我们有一些截止日期。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-03
    • 2020-05-08
    • 1970-01-01
    • 2016-05-18
    • 1970-01-01
    • 2015-01-25
    相关资源
    最近更新 更多