11 Stimmen

ejb lookup schlägt mit NamingException fehl

Ich habe Folgendes in meine web.xml eingefügt:

<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>

Der folgende Java-Code gibt mir 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;
    }
}

Der Code wird innerhalb des Containers verwendet. Damit meine ich, dass die WAR-Datei auf dem Server (Sun Application Server) bereitgestellt wird.

StackTrace (nach jsight's Vorschlag):

>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)

37voto

Arthur Ronald Punkte 32423

Ich denke, Sie wollen auf eine EJB-Anwendung (bekannt als EJB-Modul) von einer Web-Anwendung in Sun Application Server zugreifen, richtig?

OK, los geht's.

Wenn Sie eine EJB auf einem Anwendungsserver bereitstellen, gibt der Anwendungsserver ihr eine Adresse - die so genannte globale JNDI-Adresse -, damit Sie darauf zugreifen können (so etwas wie Ihre Adresse). Sie ändert sich von einem Anwendungsserver zum anderen.

In JBoss Application Server können Sie die globale JNDI-Adresse (nach dem Start) unter folgender Adresse finden

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

Wenn Sie in Sun Application Server (nach dem Start) die globale JNDI-Adresse sehen möchten, gehen Sie wie folgt vor

Rufen Sie die Verwaltungskonsole unter der folgenden Adresse auf

http://127.0.0.1:4848/asadmin

Und klicken JNDI-Durchsuchung

Wenn Ihr EJB nicht genau dort registriert ist, stimmt etwas nicht

EJB gibt es in zwei Varianten: EJB 2.1 und EJB 3.0. Worin besteht also der Unterschied?

Sieh an, sieh an, sieh an...

Beginnen wir mit EJB 2.1

  1. Erstellen einer Home-Oberfläche

Sie definiert Methoden zum ERSTELLEN, Zerstören und Finden von lokalen oder entfernten EJB-Objekten. Sie fungieren als Lebenszyklus-Schnittstellen für die EJB-Objekte. Alle Home-Schnittstellen müssen die Standardschnittstelle javax.ejb.EJBHome erweitern - wenn Sie ein Remote-EJB-Objekt verwenden - oder javax.ejb.EJBLocalHome - wenn Sie ein lokales EJB-Objekt verwenden.

// 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;

}

Application Server erstellt Home-Objekte als eine Möglichkeit, ein EJB-Objekt zu erhalten, sonst nichts.

Kümmern Sie sich um Folgendes

Die Remote-Home-Schnittstelle einer Session Bean MUSS EINE ODER MEHRERE create<METHOD>-Methoden definieren. Eine zustandslose Session Bean MUSS genau eine <METHOD>-Methode ohne Argumente DEFINIEREN.

...

throws-Klausel MUSS javax.ejb.CreateException einschließen

...

Wenn Ihre Home-Schnittstelle javax.ejb.EJBHome erweitert, MUSS die throws-Klausel die java.rmi.RemoteException einschließen. Wenn sie javax.ejb.EJBLocalHome erweitert, MUSS die java.rmi.RemoteException NICHT enthalten sein.

...

Jede Erstellungsmethode einer zustandsbehafteten Session Bean MUSS mit create<METHOD> benannt werden, und sie muss einer der Init-Methoden oder ejbCreate<METHOD>-Methoden entsprechen, die in der Session Bean-Klasse definiert ist. Die passende ejbCreate<METHOD>-Methode MUSS DIE GLEICHE ANZAHL UND ART DER ARGUMENTE HABEN. Die Erstellungsmethode für eine zustandslose Session Bean MUSS NAMEN erstellen. muss aber nicht über eine passende "ejbCreate"-Methode verfügen.


Erstellen Sie nun eine Geschäftsschnittstelle, um die Geschäftslogik in unserem EJB-Objekt zu definieren

// 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;

}

Kümmern Sie sich nun um Folgendes

Wenn Sie ein entferntes EJB-Objekt verwenden, MÜSSEN entfernte Schnittstellenmethoden KEINE lokalen Schnittstellentypen oder lokale Heimatschnittstellentypen EXPOSEN.

...

Wenn Ihre Home-Schnittstelle javax.ejb.EJBObject erweitert, MUSS die throws-Klausel die java.rmi.RemoteException einschließen. Wenn sie javax.ejb.EJBLocalObject erweitert, MUSS die java.rmi.RemoteException NICHT enthalten sein.


Jetzt ist unser 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
    };

}

Kümmern Sie sich nun um Folgendes

Sie MUSS javax.ejb.SessionBean IMPLEMENTIEREN. Sie definiert vier Methoden, die oben nicht gezeigt werden: setSessionContext, ejbRemove, ejbPassivate und ejbActivate.

Beachten Sie unsere Bohne IMPLEMENTIERT NICHT unsere Geschäftsschnittstelle aufgrund der EJB-Spezifikation sagt:

Für jede Methode, die in der Schnittstelle definiert ist, gibt es muss eine passende Methode sein in der Klasse der Sitzungsbohne. Die passende Methode muss haben:

  • Derselbe Name
  • Die gleiche Anzahl und Art der Argumente und der gleiche Rückgabetyp.
  • Alle Ausnahmen, die in der throws-Klausel der entsprechenden Methode der Sitzung definiert sind Bean-Klasse definiert sind, müssen in der throws-Klausel der Methode der lokalen Schnittstelle definiert sein.

Und SIE MÜSSEN eine ejb-jar.xml-Datei gemäß den folgenden Bestimmungen deklarieren

<?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>

Wenn Sie kein lokales EJB-Objekt haben, entfernen Sie es aus dem obigen Bereitstellungsdeskriptor

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

Wenn Sie kein entferntes EJB-Objekt haben, entfernen Sie es aus dem obigen Bereitstellungsdeskriptor

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

Und in das META-INF-Verzeichnis legen

Unsere jar-Datei wird Folgendes enthalten

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

Jetzt ist unser 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() {

    }

}

Sonst nichts,

In JBoss legen Sie die jar-Datei in

<JBOSS_HOME>/server/default/deploy

In der Verwaltungskonsole von Sun Application Server (nach dem Start)

http://127.0.0.1:4848/asadmin

Und greifen Sie auf EJB-Module zu, um Ihre ejb-jar-Datei einzusetzen

Da Sie einige Probleme bei der Bereitstellung Ihrer Anwendung in NetBeans haben, schlage ich Folgendes vor

  1. Erstellen Sie eine einfache Java-Bibliothek PROJECT (ein einfaches jar ohne Hauptmethode)
  2. Fügen Sie /server/default/lib (enthält jar-Dateien, um Ihre EJBs abzurufen) jar-Dateien zu Ihrer Java-Anwendung hinzu, wenn Sie JBoss verwenden (ich weiß nicht, welches Verzeichnis in Sun Application Server)
  3. Obigen Code implementieren

Erstellen Sie nun ein weiteres Kriegsprojekt

  1. Fügen Sie unser soeben erstelltes Projekt hinzu und fügen Sie <JBOSS_HOME>/client hinzu (enthält jar-Dateien für den Zugriff auf unsere EJBs). Auch hier weiß ich nicht, welches Verzeichnis im Sun Application Server. Schauen Sie in der Dokumentation nach.
  2. Siehe die globale Zuordnungsadresse, die oben in der Antwort angezeigt wird

Und implementieren Sie den folgenden Code in Ihr Servlet oder etwas anderes, wenn Sie JBoss verwenden

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);
}

Oder wie folgt, wenn Sie Sun Application Server verwenden: Legen Sie die Datei appserv-rt.jar (ich weiß nicht, in welcher Vergangenheit appserv-rt.jar in Sun Application Server enthalten ist) in Ihren Klassenpfad

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

    return new javax.naming.InitialContext();

}

Für den Zugriff auf Ihre EJB in unserem Servlet oder etwas anderem

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

myBean.doSomething();

Grüße,

1voto

Pascal Thivent Punkte 548176

Korrigieren Sie zunächst Ihre web.xml und fügen Sie die Remote-Schnittstelle hinzu:

<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>

Dann, in Bezug auf die java.lang.NoSuchMethodError Sean hat recht, Sie haben eine Diskrepanz zwischen der Version der App-Server-"Client-Bibliothek", die Sie in NetBeans verwenden, und der App-Server-Version (serverseitig). Ich kann Ihnen nicht genau sagen, welche JARs Sie angleichen müssen, lesen Sie dazu die Sun Application Server Dokumentation.

PS: Dies ist keine direkte Antwort auf das Problem, aber ich glaube nicht, dass Sie derzeit irgendwelche nützlichen Eigenschaften übergeben, wenn Sie Ihren ursprünglichen Kontext mit den Ergebnissen des Aufrufs von System.getProperties() In diesen Eigenschaften ist nichts Hilfreiches enthalten, um die Umgebung eines Kontexts zu definieren (z. B. die anfängliche Kontextfabrik). Verweisen Sie auf die InitialContext javadocs für weitere Details.

1voto

Sean Owen Punkte 64909

Die letzten beiden Antworten sind insofern richtig, als es sich um Dinge handelt, die Sie ändern/beheben müssen. Aber der NoSuchMethodError, den Sie sehen, stammt weder von Ihrem Code, noch von Dingen, die versuchen, Ihren Code zu finden (würde eine Art NoClassDefFoundException erzeugen, denke ich, wenn dies der Fall wäre). Das sieht eher nach inkompatiblen Versionen des JNDI-Providers aus, der vom Container bereitgestellt wird, und dem, was die JNDI-Implementierung in der Java-Bibliothek will. Das ist eine ziemlich vage Antwort, aber ich könnte mir vorstellen, dass es lösbar ist, indem Sie vielleicht Ihren Anwendungsserver aktualisieren und sicherstellen, dass Sie keine möglicherweise veralteten Kopien von Infrastrukturklassen im Zusammenhang mit JNDI mit Ihrer Anwendung bereitstellen, die stören könnten.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X