我在Tapestry应用程序中检索EJB时遇到问题。 应用程序的另一部分是在OSGi包中,所有部分都部署在Glassfish上。
目前,这就是我的东西:
我的界面(打包为jar):
@Remote
public interface MyEJBInterface {
public static final String JNDI_NAME = "ejb/MyEJBInterface";
public String sayHello(String name);
}
我的实现(打包为bundle):
@Stateless
@EJB(name = MyEJBInterface.JNDI_NAME, beanInterface = MyEJBInterface.class)
public class MyEJBImplementation implements MyEJBInterface {
@Override
public String sayHello(String name) {
return "Hello " + name;
}
}
AppModule类中的我的Tapestry构建方法:
public MyEJBService buildMyEJBService() {
MyEJBInterface myEjb = new JndiLookupHelper<MyEJBInterface>().lookupNoPrefix(MyEJBInterface.JNDI_NAME);
MyEJBService service = new MyEJBServiceMock(myEjb);
return service;
}
我这样看:
public class JndiLookupHelper<T> {
private T remoteObject;
public T lookupNoEjbPrefix(String name) {
String jndiPath = "java:comp/env/" + name;
try {
InitialContext ic = new InitialContext();
remoteObject = (T) ic.lookup(jndiPath);
} catch (NamingException ne) {
ne.printStackTrace();
}
return remoteObject;
}
}
我的问题是找不到EJB并抛出异常:
javax.naming.NamingException: Lookup failed for 'java:comp/env/ejb/MyEJBInterface' in SerialContext[myEnv={java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl, java.naming.factory.url.pkgs=com.sun.enterprise.naming} [Root exception is javax.naming.NameNotFoundException: No object bound to name java:comp/env/ejb/MyEJBInterface]
答案 0 :(得分:1)
你可能会发现这更好:
public static class EjbServiceBuilder<T> implements ServiceBuilder<T> {
private Class<T> type;
private String name;
public EjbServiceBuilder<T>(Class<T> type, String name) {
this.type= type;
this.name = name;
}
public T buildService(ServiceResources resources) {
try {
return type.cast(InitialContext.doLookup(name));
} catch (NamingException e) {
throw new RuntimeException(e);
}
}
}
public static void bind(ServiceBinder binder) {
binder.bind(MyEJBInterface.class, new EjbServiceBuilder<MyEJBInterface>(MyEJBInterface.class, MyEJBInterface.JNDI_NAME));
binder.bind(MyEJBOtherInterface.class, new EjbServiceBuilder<MyEJBOtherInterface>(...));
// MyEJBInterface will be injected into MyEJBServiceMock constructor
binder.bind(MyEJBService.class, MyEJBServiceMock.class);
}
答案 1 :(得分:0)
您需要在manifest.mf
中声明Export-EJB: ALL
我不确定EJB是否可以在“java:comp / env /”下使用。您可能需要通过portable global JNDI name
进行查找答案 2 :(得分:0)
我终于达成了解决方案。这是:
界面:
public interface MyEJBInterface {
public static final String JNDI_NAME = "java:global/ejb/MyEJBInterface";
public String sayHello(String name);
}
实施:
@Stateless
@EJB(name = MyEJBInterface.JNDI_NAME, beanInterface = MyEJBInterface.class)
public class MyEJBImplementation implements MyEJBInterface {
@Override
public String sayHello(String name) {
return "Hello " + name;
}
}
构建方法:
public MyEJBService buildMyEJBService() {
MyEJBInterface myEjb = new JndiLookupHelper<MyEJBInterface>().lookup(MyEJBInterface.JNDI_NAME);
MyEJBService service = new MyEJBServiceMock(myEjb);
return service;
}
查找:
public class JndiLookupHelper<T> {
private T remoteObject;
@SuppressWarnings("unchecked")
public T lookup(String name) {
try {
remoteObject = (T) InitialContext.doLookup(name);
} catch (NamingException ne) {
ne.printStackTrace();
}
return remoteObject;
}
}