在多模块项目中通过本地接口查找 EJB

Lookup an EJB by local interface in a multi module project

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

项目-xxx:

@Stateless
class EjbXBean implements EjbX {

}

容器通过 JNDI 注册:java:global/project-xxx/EjbXBean

项目年:

@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);

但是我不知道是什么模块(project-yyy or project-xxx),只知道ServiceLocator里面有本地接口。我不能只使用带有模块名称的整个 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) 中。

为什么需要不同的模块?将所有东西合而为一 WAR 将允许您只 @Inject Beans。 (您只需要在每个包含托管 bean 的 war 中有一个 beans.xml

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

为了确保名称可用,也许您应该考虑使用 arquillian 进行测试。 但是我会完全摆脱本地 bean 的命名服务问题。

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

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