EJB 3.2 - Can't configure the remote client correctly

617 Views Asked by At

I'm new to EJB and I've wrote a very small ejb component for demonstration purposes. All It's supposed to do is print "hello ". Currently struggling to configure the InitialContext of the remote client correctly. The container I use is JBoss 7.0. I use JaveEE7.0 with ejb3.2.

The Interface of the ejb:

package hello;

public interface Hello {

    public String sayHello(String name);
}

The bean itself:

package hello;

import javax.ejb.Remote;
import javax.ejb.Stateless;

@Stateless(name="HelloEJB")
@Remote(Hello.class)
public class HelloBean implements Hello {

    @Override
    public String sayHello(String name) {
        return "Hello, " + name;
    }

}

And the remote client that I placed inside the EJB project but I run as a java application:

package client;

import hello.Hello; 

import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.rmi.PortableRemoteObject;

public class Test {

    public static void main(String[] args) {

        Hello statelessHello = null;
        try {
            statelessHello = lookupStatelessHello(); // the method that throws exception
        } catch (NamingException e) {
            System.out.println("Bean Loading Failed");
            e.printStackTrace();
            Thread.currentThread().stop();
        }       
        Hello stub=(Hello)PortableRemoteObject.narrow(statelessHello, Hello.class);
        System.out.println("obtained a remote stateless hello for invocation");
        System.out.println(stub.sayHello(args[0]));
    }



    private static Hello lookupStatelessHello() throws NamingException {
    // the problematic code:
            Properties jndiProperties = new Properties();
            jndiProperties.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");
            jndiProperties.put(Context.PROVIDER_URL,"remote://localhost:4447"); // tried to change ports.
            jndiProperties.put("jboss.naming.client.ejb.context", true);
            Context context = new InitialContext(jndiProperties); // exception happens here
            return (Hello) context.lookup("stateless1/HelloEJB!hello.Hello");
        }
    }

When I run JBoss, I manage to deploy my ejb project without problems:

13:37:20,141 INFO [org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service thread 1-6) JNDI bindings for session bean named HelloEJB in deployment unit deployment "stateless1.jar" are as follows:

java:global/stateless1/HelloEJB!hello.Hello java:app/stateless1/HelloEJB!hello.Hello java:module/HelloEJB!hello.Hello
java:global/stateless1/HelloEJB java:app/stateless1/HelloEJB
java:module/HelloEJB

13:37:20,255 INFO [org.jboss.as.server.controller] (DeploymentScanner-threads - 2) Deployed "stateless1.jar"

but when I try to call the ejb from remote client I get:

Bean Loading Failed javax.naming.NoInitialContextException: Cannot instantiate class: org.jboss.naming.remote.client.InitialContextFactory [Root exception is java.lang.ClassNotFoundException: org.jboss.naming.remote.client.InitialContextFactory] at javax.naming.spi.NamingManager.getInitialContext(Unknown Source) at javax.naming.InitialContext.getDefaultInitCtx(Unknown Source) at javax.naming.InitialContext.init(Unknown Source) at javax.naming.InitialContext.(Unknown Source) at client.Test.lookupStatelessHello(Test.java:34) at client.Test.main(Test.java:18) Caused by: java.lang.ClassNotFoundException: org.jboss.naming.remote.client.InitialContextFactory at java.net.URLClassLoader.findClass(Unknown Source) at java.lang.ClassLoader.loadClass(Unknown Source) at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source) at java.lang.ClassLoader.loadClass(Unknown Source) at java.lang.Class.forName0(Native Method)

I've tried to change ports, tried to add security credentials but I can't understand how to add a user, tried to read guides but frankly because i'm new to this It's pretty hard for me. Also, I'm pretty sure that the way I lookup my bean is wrong, but It's not the issue right now.

I hope you'll be able to help me find the thing that I do wrong here. If you need more info on the setup, just ask.

3

There are 3 best solutions below

0
On BEST ANSWER

As stated above you need to required jboss-client.jar along with your code , in order this to work. The specific jar can be found at

JBOSS_HOME/bin/client/jboss-client-7.1.0.Final.jar.

Also please have a look on the official documentation and wiki that comes along with a full example. See here.

0
On

Your client has classes missing from its class path.

Have a look at the $JBOSS_HOME/bin/client/README-EJB-JMS.txt file for information regarding what jars that you need to include with your client.

0
On
  1. Ensure client*.jar is in your class-path in my case gf-client.jar, coz using glassfish not JBoss.
  2. client code change read comments 2 ways to look up...
  3. ejb Stateless(name = "HelloWorldEJB", mappedName="HelloEJB") should be used only with name as its portable and mappedName is vendor locked should be discouraged i have only used it for illustration purpose.
  4. Also i have not set up jndi props as its in same container.

Context context = new InitialContext();

  1. post code change redeploy or restart JBoss.

The working code is below paste and run ;)

import javax.ejb.Remote;

@Remote
public interface HelloI {

    public String sayHello(String name);
}

  import javax.ejb.Remote;
    import javax.ejb.Stateless;
    
    @Stateless(name = "HelloWorldEJB", mappedName="HelloEJB")
    @Remote(HelloI.class)
    public class Hello implements HelloI {
        @Override
        public String sayHello(String name) {
            return "Hello, " + name;
        }
    
    }

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.rmi.PortableRemoteObject;

public class HelloT {

    public static void main(String[] args) {

        HelloI statelessHelloI = null;
        try {
            statelessHelloI = lookupStatelessHello(); // the method that throws exception
        } catch (NamingException e) {
            System.out.println("Bean Loading Failed");
            e.printStackTrace();
            Thread.currentThread().stop();
        }
        HelloI stub=(HelloI) PortableRemoteObject.narrow(statelessHelloI, HelloI.class);
        System.out.println("obtained a remote stateless hello for invocation");
        System.out.println(stub.sayHello(args[0]));
    }



    private static HelloI lookupStatelessHello() throws NamingException {
        // the problematic code:
        /*Properties jndiProperties = new Properties();
        jndiProperties.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");
        jndiProperties.put(Context.PROVIDER_URL,"remote://localhost:4447"); // tried to change ports.
        jndiProperties.put("jboss.naming.client.ejb.context", true);
        Context context = new InitialContext(jndiProperties); // exception happens here*/
        Context context = new InitialContext();
        return (HelloI) context.lookup("HelloEJB");
    }
}

output Jul 18, 2020 5:58:07 PM obtained a remote stateless hello for invocation Hello, ani

Process finished with exit code 0

Most of your code I have left untouched in above post .The above client code could be simplified as

import com.au.ejbs.HelloI;

import javax.naming.Context;
import javax.naming.InitialContext;

public class HelloT2 {

    public static void main(String[] args)throws Exception {
       Context context = new InitialContext();
    HelloI remote = (HelloI) context.lookup("HelloEJB");//resolves to mappedName @Stateless(name = "HelloWorldEJB", mappedName="HelloEJB"), from what I read could be glassfish and weblogic centric.
    System.out.println(remote.sayHello(args[0]));
    remote = (HelloI) context.lookup("java:global/ejb3_2_ear_exploded/ejb/HelloWorldEJB");//Portable should work on jboss and any container resolves to Stateless(name = "HelloWorldEJB"
    System.out.println(remote.sayHello(args[0]));
    }
}