Ejb lookup не работает с NamingException

Я добавил следующее в свой web.xml:

<ejb-ref>
        <ejb-ref-name>ejb/userManagerBean</ejb-ref-name>
        <ejb-ref-type>Session</ejb-ref-type>
        <home>gha.ywk.name.entry.ejb.usermanager.UserManagerHome</home>
        <remote>what should go here??</remote>
</ejb-ref>

Следующий java-код дает мне NamingException:

public UserManager getUserManager () throws HUDException {
    String ROLE_JNDI_NAME = "ejb/userManagerBean";
    try {
        Properties props = System.getProperties();
        Context ctx = new InitialContext(props);
        UserManagerHome userHome = (UserManagerHome) ctx.lookup(ROLE_JNDI_NAME);
        UserManager userManager = userHome.create();
        WASSSecurity user = userManager.getUserProfile("user101", null);
        return userManager;
    } catch (NamingException e) {
        log.error("Error Occured while getting EJB UserManager" + e);
        return null;
    } catch (RemoteException ex) {
        log.error("Error Occured while getting EJB UserManager" + ex);
        return null;
    } catch (CreateException ex) {
        log.error("Error Occured while getting EJB UserManager" + ex);
        return null;
    }
}

Код используется внутри контейнера. Под этим я подразумеваю, что .WAR развертывается на сервере (Sun Application Server).

StackTrace (после предложения jsight):

>Exception occurred in target VM: com.sun.enterprise.naming.java.javaURLContext.<init>(Ljava/util/Hashtable;Lcom/sun/enterprise/naming/NamingManagerImpl;)V 
java.lang.NoSuchMethodError: com.sun.enterprise.naming.java.javaURLContext.<init>(Ljava/util/Hashtable;Lcom/sun/enterprise/naming/NamingManagerImpl;)V
 at com.sun.enterprise.naming.java.javaURLContextFactory.getObjectInstance(javaURLContextFactory.java:32)
 at javax.naming.spi.NamingManager.getURLObject(NamingManager.java:584)
 at javax.naming.spi.NamingManager.getURLContext(NamingManager.java:533)
 at javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:279)
 at javax.naming.InitialContext.lookup(InitialContext.java:351)
 at gov.hud.pih.eiv.web.EjbClient.EjbClient.getUserManager(EjbClient.java:34)

Ответ 1

Я думаю, вы хотите получить доступ к EJB-приложению (известному как модуль EJB) из веб-приложения на Sun Application Server, верно?

ok, отпустите.

Когда вы развертываете EJB на сервере приложений, сервер приложений дает ему адрес - известный как глобальный адрес JNDI - как способ доступа к нему (что-то вроде вашего адреса). Он изменяется с сервера приложений на другой.

В JBoss Application Server вы можете увидеть глобальный адрес JNDI (после его запуска) в следующем адресе

http://127.0.0.1:8080/jmx-console/HtmlAdaptor

В Sun Application Server, если вы хотите увидеть глобальный адрес JNDI (после его запуска), выполните следующие

Доступ к консоли администратора по следующему адресу

http://127.0.0.1:4848/asadmin

И нажмите JNDI-просмотр

Если ваш EJB НЕ зарегистрирован прямо там, что-то не так.

EJB поставляется в двух вариантах: EJB 2.1 и EJB 3.0. Так в чем же разница?

Ну, хорошо, хорошо...

Начнем с EJB 2.1

  • Создать домашний интерфейс

Он определяет методы СОЗДАНИЯ, уничтожения и поиска локальных или удаленных объектов EJB. Он действует как интерфейсы жизненного цикла для объектов EJB. Все домашние интерфейсы должны расширять стандартный интерфейс javax.ejb.EJBHome - если вы используете удаленный объект ejb - или javax.ejb.EJBLocalHome - если вы используете локальный объект EJB.

// a remote EJB object - extends javax.ejb.EJBHome
// a local EJB object - extends javax.ejb.EJBLocalHome
public interface MyBeanRemoteHome extends javax.ejb.EJBHome {

    MyBeanRemote create() throws javax.ejb.CreateException, java.rmi.RemoteException;

}

Сервер приложений будет создавать домашние объекты таким образом, чтобы вы могли получить объект EJB, и ничего больше.

Позаботьтесь о следующем

Сессия bean s удаленный домашний интерфейс ДОЛЖЕН ОПРЕДЕЛИТЬ ОДИН ИЛИ БОЛЬШЕ создавать < МЕТОД > методы. Сеанс без состояния bean ДОЛЖЕН ОПРЕДЕЛАТЬ точно один < МЕТОД > метод без аргументов.

...

Предложение

throws ДОЛЖНО ВКЛЮЧИТЬ javax.ejb.CreateException

...

Если ваш домашний интерфейс расширяет javax.ejb.EJBHome, предложения бросков ДОЛЖНЫ ВКЛЮЧАТЬ java.rmi.RemoteException. Если он расширяет javax.ejb.EJBLocalHome, НЕ ДОЛЖЕН ВКЛЮЧАТЬ java.rmi.RemoteException.

...

Каждый метод создания сеанса с состоянием bean ДОЛЖЕН БЫТЬ ИМЕНИ, создавая < МЕТОД > , и он должен соответствовать одному из методов Init или ejbCreate <METHOD> методы, определенные в сеансе bean класс. Соответствующий ejbCreate <METHOD> метод ДОЛЖЕН ИМЕЕТ ТО ЖЕ ЧИСЛО И ТИПЫ АРГУМЕНТОВ. Метод create для сеанса без состояния bean ДОЛЖЕН БЫТЬ ИМЕНИ, но не должен иметь соответствующий метод "ejbCreate".


Теперь создайте бизнес-интерфейс, чтобы определить бизнес-логику в нашем объекте EJB

// a remote EJB object - extends javax.ejb.EJBObject
// a local EJB object - extends javax.ejb.EJBLocalObject
public interface MyBeanRemote extends javax.ejb.EJBObject {

    void doSomething() throws java.rmi.RemoteException;

}

Теперь позаботьтесь о следующем

Если вы используете удаленный объект EJB, методы удаленного интерфейса НЕ ДОЛЖНЫ ЭКСПОЗИРОВАТЬ типы локального интерфейса или типы локального домашнего интерфейса.

...

Если ваш домашний интерфейс расширяет javax.ejb.EJBObject, предложения throw ДОЛЖНЫ ВКЛЮЧАТЬ java.rmi.RemoteException. Если он расширяет javax.ejb.EJBLocalObject, НЕ ДОЛЖЕН ВКЛЮЧАТЬ java.rmi.RemoteException.


Теперь наш EJB

public class MyBean implements javax.ejb.SessionBean {

    // why create method ? Take a special look at EJB Home details (above)
    public void create() {
        System.out.println("create");
    }

    public void doSomething() throws java.rmi.RemoteException {
        // some code
    };

}

Теперь позаботьтесь о следующем

Он ДОЛЖЕН ОСУЩЕСТВИТЬ javax.ejb.SessionBean. Он определяет четыре метода - не показано выше: setSessionContext, ejbRemove, ejbPassivate и ejbActivate.

Обратите внимание, что наш bean НЕ РЕАЛИЗАЦИЯ наш бизнес-интерфейс из-за спецификации EJB говорит:

Для каждого метода, определенного в интерфейсе, должен быть метод сопоставления в классе сеанса bean. Метод сопоставления должен иметь:

  • То же имя
  • То же количество и типы аргументов и один и тот же тип возврата.
  • Все исключения, определенные в предложении throws метода сопоставления сессии bean класс должен быть определен в предложении throws метода локального интерфейса.

И ВЫ ДОЛЖНЫ ЗАЯВЛЯТЬ файл ejb-jar.xml в соответствии с

<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd" version="2.1">
    <enterprise-beans>
        <session>
            <ejb-name>HelloWorldEJB</ejb-name>
            <home>br.com.MyBeanRemoteHome</home>
            <remote>br.com.MyBeanRemote</remote>
            <local-home>br.com.MyBeanLocalHome</local-home>
            <local>br.com.MyBeanLocal</local>
            <ejb-class>br.com.MyBean</ejb-class>
            <session-type>Stateless</session-type>
            <transaction-type>Container</transaction-type>
        </session>
    </enterprise-beans>
</ejb-jar>

Если у вас нет локального объекта EJB, удалите из дескриптора развертывания выше

<local-home>br.com.MyBeanLocalHome</local-home>
<local>br.com.MyBeanLocal</local>

Если у вас нет удаленного объекта EJB, удалите из дескриптора развертывания выше

<home>br.com.MyBeanRemoteHome</home>
<remote>br.com.MyBeanRemote</remote>

И введите каталог META-INF

Наш файл jar будет содержать следующие

/META-INF/ejb-jar.xml
br.com.MyBean.class
br.com.MyBeanRemote.class
br.com.MyBeanRemoteHome.class

Теперь наш EJB 3.0

// or @Local
// You can not put @Remote and @Local at the same time
@Remote
public interface MyBean {

    void doSomething();

}

@Stateless
public class MyBeanStateless implements MyBean {

    public void doSomething() {

    }

}

Ничего другого,

В JBoss помещен файл jar в

<JBOSS_HOME>/server/default/deploy

В Sun Application Server доступ (после запуска) консоль администратора

http://127.0.0.1:4848/asadmin

И получить доступ к модулям EJB для развертывания файла ejb-jar

Поскольку у вас есть некоторые проблемы при развертывании приложения в NetBeans, я предлагаю следующее

  • Создайте простую библиотеку Java PROJECT (простая банка без основного метода)
  • Добавьте/сервер/default/lib (содержит файлы jar для получения ваших EJB) jar файлов в ваше Java-приложение, используете ли вы JBoss (я не знаю, какой каталог на Sun Application Server)
  • Внедрить код выше

Теперь создайте еще один военный ПРОЕКТ

  • Добавьте наш проект, созданный чуть выше, и добавьте <JBOSS_HOME > /client (содержит файлы jar для доступа к нашим EJB). Опять же, я не знаю, какой каталог на Sun Application Server. Ckeck из документации.
  • См. его глобальный адрес отображения, как показано в верхней части ответа

И реализуйте следующий код в своем сервлете или что-то еще, используете ли вы JBoss

public static Context getInitialContext() throws javax.naming.NamingException {

    Properties p = new Properties();
    p.put(Context.INITIAL_CONTEXT_FACTORY,        "org.jnp.interfaces.NamingContextFactory");
    p.put(Context.URL_PKG_PREFIXES, " org.jboss.naming:org.jnp.interfaces");
    p.put(Context.PROVIDER_URL, "jnp://127.0.0.1:1099");

    return new javax.naming.InitialContext(p);
}

Или следуйте, используете ли вы Sun Application Server - поместите файл appserv-rt.jar(я не знаю, какое прошлое содержит appserv-rt.jar в Sun Application Server) в вашем пути к классам

public static Context getInitialContext() throws javax.naming.NamingException {

    return new javax.naming.InitialContext();

}

Чтобы получить доступ к EJB в нашем сервлете или что-то еще

MyBeanRemote myBean = (MyBeanRemote) getInitialContext().lookup(<PUT_EJB_GLOBAL_ADDRESS_RIGHT_HERE>);

myBean.doSomething();

С уважением,

Ответ 2

Возможно, строка поиска должна быть: "java: comp/env/ejb/userManagerBean"?

Ответ 3

Сначала исправьте свой web.xml и добавьте в него Удаленный интерфейс:

<ejb-ref>
  <description>Sample EJB</description>
  <ejb-ref-name>SampleBean</ejb-ref-name>
  <ejb-ref-type>Session</ejb-ref-type>
  <home>com.SampleHome</home>
  <remote>com.Sample</remote> <!-- the remote interface goes here -->
</ejb-ref>

Затем, в отношении java.lang.NoSuchMethodError, Шон прав, у вас есть несоответствие между версией "клиентской библиотеки" сервера приложений, которую вы используете внутри NetBeans и версии сервера приложений (на стороне сервера). Я не могу точно сказать, какие JAR-ы вам нужно выровнять, обратитесь к документации Sun Application Server.

PS: Это не прямой ответ на проблему, но я не думаю, что вы передаете какие-либо полезные свойства при создании исходного контекста с результатами вызова System.getProperties(), нет ничего полезного в этих свойства для определения среды контекста (например, начальный контекст factory). Подробнее см. InitialContext javadocs.

Ответ 4

Последние два ответа верны в том, что они - вещи, которые вам нужно изменить/исправить. Но NoSuchMethodError, который вы видите, не из вашего кода, ни из-за того, что вы пытаетесь найти свой код (я бы подумал, что это приведет к каким-то NoClassDefFoundException). Это больше похоже на несовместимые версии поставщика JNDI, предоставляемые контейнером, и то, что хочет реализовать JNDI в библиотеке Java. Это довольно расплывчатый ответ, но, возможно, он может решить, возможно, обновив ваш сервер приложений и, гарантируя, что вы не развертываете, возможно, устаревшие копии классов инфраструктуры, связанных с JNDI с вашим приложением, которые могут мешать.