我有一个从servlet实例化的POJO。我需要在这个POJO中查找EJB,CDI或JNDI。我的JEE容器是TomEE 1.6.0。
我的问题是:需要EJB有远程接口吗?因为如果我通过@EJB直接从servlet实例化它,远程接口就不需要......
只需看看这个总是抛出NameNotFoundException的简单示例。
@Stateless
public class MyEJB
{
public String sayHello()
{
return "Hello";
}
}
下一个servlet尝试你查找MyEJB:
@WebServlet("/myServlet")
public class MyServlet extends HttpServlet
{
private static final long serialVersionUID=1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,IOException
{
try
{
Context ctx = new InitialContext();
MyEJB ejb = (MyEJB) ctx.lookup("MyEJB");
System.out.println(ejb.sayHello());
}
catch(Exception ex)
{
ex.printStackTrace();
throw new RuntimeException(ex);
}
}
}
行:MyEJB ejb = (MyEJB) ctx.lookup("MyEJB");
总是抛出NameNotFoundException。但是,如果我使用@EJB,它可以正常工作。但是我需要在JNDI模式下进行查找,因为最后我将在POJO中实例化这个EJB。
那么,为什么这次查找失败了?
答案 0 :(得分:1)
这与远程接口无关。
当你使用@EJB在servlet中声明MyEJB时,它可以工作,因为servlet是容器管理的 - 你的TomEE服务器实例化servlet对象。但是,在MyPojo(也使用@EJB)中声明MyEJB将不起作用,因为MyPojo 不容器管理 - 它是使用新的MyPojo()而不是TomEE服务器创建的。
例如,您可以使MyPojo成为另一个EJB(使用@Stateless)并使用@EJB将其注入servlet - 而不是通过创建新的MyPojo()。
答案 1 :(得分:0)
我可以通过使用这个简单的类对JNDI树进行内省来解决这个问题:
import javax.naming.Binding;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NameClassPair;
import javax.naming.NamingEnumeration;
public class JndiInstrospector
{
public static void print()
{
try
{
Context ctx = new InitialContext();
String n = ctx.getNameInNamespace();
_print(n);
}
catch(Exception ex)
{
ex.printStackTrace();
throw new RuntimeException();
}
}
private static void _print(String name) throws Exception
{
try
{
System.out.println("Name in manespace: "+name);
Context ctx = new InitialContext();
NamingEnumeration<Binding> list = ctx.listBindings(name);
while( list.hasMoreElements() )
{
Binding b = list.nextElement();
String s = b.getName();
_print(name+"/"+s);
}
}
catch(Exception ex)
{
// ignore
}
}
}
最后,我希望查找的EJB位于: “java:/ openejb / local / FacadeBeanLocalBean”,其中FacadadeBean是我的EJB(无状态会话bean)的名称。