如何从servlet上下文中查找EJB?

时间:2014-05-22 13:59:33

标签: servlets ejb tomee

我有一个从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。

那么,为什么这次查找失败了?

2 个答案:

答案 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)的名称。