11

I've added the following in my 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>

The following java code is giving me 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;
    }
}

The code is used inside the container. By that I mean that the .WAR is deployed on the server (Sun Application Server).

StackTrace (after jsight's suggestion):

>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)
Drake
  • 2,331
  • 3
  • 19
  • 17
  • Can you provide a stack trace? Is the code executed outside or inside the container? – Andrey Adamovich Sep 24 '09 at 20:29
  • Please add your deployment descriptor too. – Pascal Thivent Sep 24 '09 at 20:54
  • 1
    deployment descriptor? I am using netbeans to deploy the application – Drake Sep 24 '09 at 20:57
  • The ejb-jar.xml file, the file that goes in the METAINF directory of your EJB module jar. – Pascal Thivent Sep 24 '09 at 21:13
  • java.lang.NoSuchMethodError? Which JARs do you include into your WAR? It seems like some class path comflict actually. – Andrey Adamovich Sep 24 '09 at 21:21
  • I never created ejb-jar.xml file. Do I need to create that in same directory where my web.xml is? and what should go in there based on my ejb-ref in web.xml? I'm new to ejb's – Drake Sep 24 '09 at 21:30
  • 2
    No, not in the web module (.war), in the EJB-JAR module (.jar). You need to learn the basics of enterprise application packaging (ear, ejb-jar, war). http://72.5.124.55/j2ee/1.4/docs/tutorial-update6/doc/Overview5.html#wp84705 – Pascal Thivent Sep 24 '09 at 21:37
  • thanks for the link. Currently when I build my app it creates one .WAR file. so you mean it should create a .jar along with that...which will contain ejb-jar.xml? – Drake Sep 24 '09 at 21:42
  • Where is the EJB deployed? On the Sun Application Server like the webapp (if so, what is the `WASSSecurity` stuff. Does this have anything to do with WebSphere? I'm doubting now... You are trying to call an EJB 2.x, right? – Pascal Thivent Sep 24 '09 at 21:48
  • I think we are on different pages. I am 'consuming' this EJB. Someone has provided a .JAR file which contains all the packages. I have this .JAR file in my libraries folder. My application builds a .WAR file. WASSSecurity has nothing to do with WebSphere. My application is deployed on Sun Application Server. WASSSecurity is just one of the classes that was provided in .JAR file. Do I need EJB-JAR when I am just using someones API's and not providing any? – Drake Sep 24 '09 at 23:12
  • Ok, this makes things clearer. The answer is no, you don't need an ejb-jar.xml file if you're client of an EJB (the provider of the EJB has taken care of that part). So forget what I said about EJB packaging and deployment, I understand now that this is out of your scope. What you need is as client of an EJB is an "EJB client jar" which has been provided (that contains the Home and Remote interfaces and all the other classes needed to use the client view of the enterprise bean). This EJB client jar has to be packaged in the WEB-INF/lib directory of your webapp but this seems to be ok. – Pascal Thivent Sep 25 '09 at 10:38
  • I had just placed the EJB JAR given to me in my applications' lib folder. I understand now that it has to be first deployed on to the application server for my code to actually use the EJB. But I am having problems deploying it to the application server. in my application server do i need to add something to an XML before being able to deploy the jar file? – Drake Sep 25 '09 at 15:07

3 Answers3

37

I think you want to access an EJB application (known as EJB module) from a web application in Sun Application Server, right ?

ok, let's go.

When you deploy an EJB into an application server, the application server gives it an address - known as global JNDI address - as a way you can access it (something like your address). It changes from an application server to another.

In JBoss Application Server, you can see global JNDI address (after starting it up) in the following address

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

In Sun Application Server, if you want to see global JNDI address (after starting it up), do the following

Access the admin console in the following address

http://127.0.0.1:4848/asadmin

And click JNDI browsing

If your EJB IS NOT registered right there, there is something wrong

EJB comes in two flavors: EJB 2.1 and EJB 3.0. So what is the difference ?

Well, well, well...

Let's start with EJB 2.1

  1. Create a Home interface

It defines methods for CREATING, destroying, and finding local or remote EJB objects. It acts as life cycle interfaces for the EJB objects. All home interfaces have to extend standard interface javax.ejb.EJBHome - if you a using a remote ejb object - or javax.ejb.EJBLocalHome - if you are using a local EJB object.

// 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 will create Home objects as a way you can obtain an EJB object, nothing else.

Take care of the following

A session bean’s remote home interface MUST DEFINE ONE OR MORE create<METHOD> methods. A stateless session bean MUST DEFINE exactly one <METHOD> method with no arguments.

...

throws clause MUST INCLUDE javax.ejb.CreateException

...

If your Home interface extends javax.ejb.EJBHome, throws clauses MUST INCLUDE the java.rmi.RemoteException. If it extends javax.ejb.EJBLocalHome, MUST NOT INCLUDE the java.rmi.RemoteException.

...

Each create method of a stateful session bean MUST BE NAMED create<METHOD>, and it must match one of the Init methods or ejbCreate<METHOD> methods defined in the session bean class. The matching ejbCreate<METHOD> method MUST HAVE THE SAME NUMBER AND TYPES OF ARGUMENTS. The create method for a stateless session bean MUST BE NAMED create but need not have a matching “ejbCreate” method.


Now create an business interface in order to define business logic in our EJB object

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

}

Now take care of the following

If you are using a remote EJB object, remote interface methods MUST NOT EXPOSE local interface types or local home interface types.

...

If your Home interface extends javax.ejb.EJBObject, throws clauses MUST INCLUDE the java.rmi.RemoteException. If it extends javax.ejb.EJBLocalObject, MUST NOT INCLUDE the java.rmi.RemoteException.


Now our 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
    };

}

Now take care of the following

It MUST IMPLEMENTS javax.ejb.SessionBean. It defines four methods - not shown above: setSessionContext, ejbRemove, ejbPassivate, and ejbActivate.

Notice our bean DOES NOT IMPLEMENT our business interface because of EJB specification says:

For each method defined in the interface, there must be a matching method in the session bean’s class. The matching method must have:

  • The same name
  • The same number and types of arguments, and the same return type.
  • All the exceptions defined in the throws clause of the matching method of the session bean class must be defined in the throws clause of the method of the local interface.

And YOU HAVE TO DECLARE a ejb-jar.xml file according to

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

If you do not have a local EJB object remove from the deployment descriptor above

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

If you do not have a remote EJB object remove from the deployment descriptor above

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

And put in META-INF directory

Our jar file will contain the following

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

Now our 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() {

    }

}

Nothing else,

In JBoss put jar file in

<JBOSS_HOME>/server/default/deploy

In Sun Application Server access (after starting it up) admin console

http://127.0.0.1:4848/asadmin

And access EJB Modules in order to deploy your ejb-jar file

As you have some problems when deploying your application in NetBeans, i suggest the following

  1. Create a simple Java library PROJECT (a simple jar without a main method)
  2. Add /server/default/lib (contains jar files in order you retrieve your EJB's) jar files to your Java application whether you are using JBoss (I do not know which directory in Sun Application Server)
  3. Implement code above

Now create another war PROJECT

  1. Add our project created just above and add <JBOSS_HOME>/client (contains jar files in order to access our EJB's). Again i do not know which directory in Sun Application Server. Ckeck out its documentation.
  2. See its global mapping address as shown in the top of the answer

And implement the following code in your Servlet or something else whether you are using 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);
}

Or the following whether you are using Sun Application Server - put the file appserv-rt.jar (I do not know which past contain appserv-rt.jar in Sun Application Server) in your classpath

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

    return new javax.naming.InitialContext();

}

In order to access your EJB in our Servlet or something else

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

myBean.doSomething();

regards,

Arthur Ronald
  • 33,349
  • 20
  • 110
  • 136
  • can you please have a look at this question. http://stackoverflow.com/questions/29190816/ejb2-javax-naming-namenotfoundexceptionexception-in-lookup – User27854 Mar 22 '15 at 05:19
1

First, fix your web.xml and add the Remote Interface in it:

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

Then, regarding the java.lang.NoSuchMethodError, Sean is right, you have a mismatch between the version of the app server "client library" you are using inside NetBeans and the app server version (server-side). I can't tell you exactly which JARs you need to align though, refer to the Sun Application Server documentation.

PS: This is not a direct answer to the problem but I don't think you're currently passing any useful properties when creating your initial context with the results of the call to System.getProperties(), there is nothing helpful in these properties to define the environment of a context (e.g. the initial context factory). Refer to the InitialContext javadocs for more details.

Pascal Thivent
  • 562,542
  • 136
  • 1,062
  • 1,124
1

Last two answers are both correct in that they are things you need to change/fix. But the NoSuchMethodError you see is not from your code, nor from things trying to find your code (would produce some kind of NoClassDefFoundException, I think, were this the case). This looks more like incompatible versions of the JNDI provider provided by the container, and what the JNDI implementation in the Java library wants. That's a pretty vague answer, but, would imagine it is solvable by perhaps upgrading your application server, and, ensuring you aren't deploying possibly-stale copies of infrastructure classes related to JNDI with your app, that might interfere.

Sean Owen
  • 66,182
  • 23
  • 141
  • 173