我正在尝试通过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。
答案 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-unit或ejb-cdi-unit(确定那是我的项目,所以我不是完全公正的;-))