Как выполнить поиск EJB из контекста сервлета?

У меня есть POJO, созданный из сервлета. Мне нужно выполнить поиск EJB в этом POJO, либо CDI, либо JNDI. Мой контейнер JEE — TomEE 1.6.0.

Мой вопрос таков: нужен ли EJB удаленный интерфейс? Потому что, если я создам экземпляр непосредственно из сервлета с помощью @EJB, удаленный интерфейс не понадобится...

Просто посмотрите на этот простой пример, который всегда генерирует исключение NameNotFoundException.

@Stateless
public class MyEJB
{
    public String sayHello()
    {
        return "Hello";
    }
}

Следующий сервлет пытается найти 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, потому что, наконец, я создам экземпляр этого EJB в POJO.

Итак, почему этот поиск не работает?


person pablosz    schedule 22.05.2014    source источник
comment
Можете ли вы просто передать EJB в POJO из сервлета? Я бы либо передал его как аргумент конструктора, либо с помощью установщика. Вы также можете просто использовать его в качестве аргумента метода. Вы должны иметь возможность внедрить его в свой сервлет.   -  person jahroy    schedule 22.05.2014


Ответы (2)


Это не имеет ничего общего с удаленными интерфейсами.

Когда вы объявляете MyEJB в сервлете, используя @EJB, это работает, потому что сервлет управляется контейнером - ваш сервер TomEE создает экземпляр объекта сервлета. Однако объявление MyEJB в MyPojo (также с использованием @EJB) не будет работать, потому что MyPojo не управляется контейнером — он создается с использованием new MyPojo(), а не сервером TomEE.

Например, вы можете сделать MyPojo еще одним EJB (используя @Stateless) и внедрить его с помощью @EJB в сервлет, а не путем создания нового MyPojo().

person Tomasz Nowak    schedule 22.05.2014
comment
) Я знаю это. Но я хочу знать, нужен ли EJB удаленный интерфейс, чтобы его можно было найти в MyPojo. Нужен удаленный интерфейс или нет? - person pablosz; 22.05.2014
comment
Нет, если POJO является локальным. - person jahroy; 22.05.2014
comment
@Tomasz Nowak Пожалуйста, взгляните на мой вопрос еще раз, я отредактировал код, чтобы он был более конкретным. - person pablosz; 26.05.2014

Я могу решить эту проблему самостоятельно, изучив дерево 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 (сеансового компонента без сохранения состояния).

person pablosz    schedule 12.06.2014