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

时间:2017-08-06 00:03:09

标签: java-ee ejb jndi service-locator

我正在尝试通过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);

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

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

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

我正在使用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);

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

1 个答案:

答案 0 :(得分:1)

为什么需要不同的模块?拥有一个WAR将允许你只有@Inject豆。 (在每个包含托管bean的战争中你只需要beans.xml

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

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

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

如果你想要基于Weld嵌入并使用hibernate的东西,也许可以考虑cdi-unitejb-cdi-unit(确定那是我的项目,所以我不是完全公正的;-))