我们目前正在开发一个旨在在WebSphere服务器上进行部署的应用程序。应用程序应使用内部服务提供程序,该服务提供程序提供对作为远程EJB实现的服务的访问。 Service Provider bean有一些硬编码的jndi名称可供使用。
现在在开发过程中我们正在使用Tomee,总的来说一切都很好。除了一件事之外: ServiceProvider执行“cell / persistent / configService”的jndi查找。现在我尝试创建一个包含这些服务的模拟EJB的模拟耳朵。我能够部署它们,并且我能够使用jndi-names从应用程序访问它们,例如:“java:global / framework-mock-ear-1.0.0-SNAPSHOT / framework-mock-impl / ConfigServiceMock”但它似乎无法使用jndi查找来访问它们:“cell / persistent / configService”...现在我在我的模拟实现中添加了一个openejb-jar.xml文件,其中包含:
<openejb-jar>
<ejb-deployment ejb-name="ConfigServiceMock">
<jndi name="cell/persistent/configService"
interface="de.thecompany.common.services.config.ConfigService"/>
</ejb-deployment>
</openejb-jar>
我可以在启动时看到bean似乎在该名称下正确注册:
INFORMATION: Jndi(name=cell/persistent/configService) --> Ejb(deployment-id=ConfigServiceMock)
但我现在已经知道如何让另一只耳朵能够使用该名称访问这个bean。
提供服务提供商部分,我们根本无法更改,因此请不要建议更改硬编码的jndi名称。我们当然希望这样做,但无法改变任何事情。
答案 0 :(得分:0)
好的......我浪费了相当多的时间。直到我终于找到了解决方案。我没有配置Tomee和OpenEJB来查找我的bean,而是劫持了InitialContext并重写了我的查询。
package de.mycompany.mock.tomee;
import org.apache.naming.java.javaURLContextFactory;
import javax.naming.Context;
import javax.naming.NamingException;
import java.util.Hashtable;
public class MycompanyNamingContextFactory extends javaURLContextFactory {
private static Context initialContext;
@Override
public Context getInitialContext(Hashtable environment) throws NamingException {
if(initialContext == null) {
Hashtable childEnv = (Hashtable) environment.clone();
childEnv.put("java.naming.factory.initial", "org.apache.naming.java.javaURLContextFactory");
initialContext = new MycompanyInitialContext(childEnv);
}
return initialContext;
}
}
通过设置系统属性
java.naming.factory.initial=de.mycompany.mock.tomee.MycompanyNamingContextFactory
我能够注入MycompanyInitialContext上下文实现:
package de.mycompany.mock.tomee;
import org.apache.openejb.core.ivm.naming.IvmContext;
import org.apache.openejb.core.ivm.naming.NameNode;
import javax.naming.NamingException;
import java.util.Hashtable;
public class MycomanyInitialContext extends IvmContext {
public MycomanyInitialContext(Hashtable<String, Object> environment) throws NamingException {
super(environment);
}
@Override
public Object lookup(String compositName) throws NamingException {
if("cell/persistent/configService".equals(compositName)) {
return super.lookup("java:global/mycompany-mock-ear-1.0.0-SNAPSHOT/mycompany-mock-impl/ConfigServiceMock");
}
if("cell/persistent/authorizationService".equals(compositName)) {
Object obj = super.lookup("java:global/mycompany-mock-ear-1.0.0-SNAPSHOT/mycompany-mock-impl/AuthServiceMock");
return obj;
}
return super.lookup(compositName);
}
}
我知道这不是很漂亮,如果有人知道如何让这更容易和更漂亮,我全心全意,这个解决方案似乎有效。因为它只是用于在开发过程中模拟生产服务,所以这个黑客并不会对我产生任何噩梦。只是想我发布它,以防其他人偶然发现类似的东西。
答案 1 :(得分:0)
我知道这个问题会在几年后问世,但是一个更简单的解决方案是按照以下方式简单地设置系统属性(例如在catalina.properties中):
java.naming.initial.factory=org.apache.openejb.core.OpenEJBInitialContextFactory
这允许您通过设置的名称查找ejb,并在启动过程中在tomee日志中显示该ejb,例如来自您的“ cell / persistent / configService”
INFORMATION: Jndi(name=cell/persistent/configService) --> Ejb(deployment-id=ConfigServiceMock)
设置系统属性后,您可以按所需方式查找ejb
final Context ctx = new InitialContext();
ctx.lookup("cell/persistent/configService")
OpenEJBInitialContextFactory允许访问本地EJB和容器资源。
如果您不想设置系统属性(因为它会影响tomee中的所有应用程序),您仍然可以使用工厂以“标准”方式对其进行设置:
Properties properties = new Properties();
properties.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.apache.openejb.core.OpenEJBInitialContextFactory");
final Context ctx = new InitialContext(properties);
ctx.lookup("cell/persistent/configService");
当然,您仍然可以使用全局“ java:global /”以及该工厂来查找它们。