EJB 3.2 - 无法正确配置远程客户端

EJB 3.2 - Can't configure the remote client correctly

我是 EJB 的新手,我已经编写了一个非常小的 ejb 组件用于演示目的。它应该做的就是打印 "hello "。目前正在努力正确配置远程客户端的 InitialContext。我使用的容器是JBoss 7.0。我将 JaveEE7.0 与 ejb3.2 一起使用。

ejb 的接口:

package hello;

public interface Hello {

    public String sayHello(String name);
}

bean 本身:

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

}

还有我放在 EJB 项目中但 运行 作为 java 应用程序的远程客户端:

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

当我 运行 JBoss 时,我成功地部署了我的 ejb 项目:

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"

但是当我尝试从远程客户端调用 ejb 时,我得到:

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)

我尝试更改端口,尝试添加安全凭证,但我不明白如何添加用户,尝试阅读指南,但坦率地说,因为我是新手,这对我来说很难。另外,我很确定我查找 bean 的方式是错误的,但现在这不是问题所在。

我希望你能帮我找到我在这里做错的地方。如果您需要有关设置的更多信息,请询问。

您的客户端 class 路径中缺少 class 个元素。

查看 $JBOSS_HOME/bin/client/README-EJB-JMS.txt 文件,了解有关您的客户端需要包含哪些 jar 的信息。

如上所述,您需要 jboss-client.jar 以及您的代码才能正常工作。具体的 jar 可以在

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

另请查看带有完整示例的官方文档和 wiki。参见 here

  1. 确保 client*.jar 在我的 class 路径中 gf-client.jar,因为使用 glassfish 而不是 JBoss。
  2. 客户端代码更改阅读评论 2 种查找方式...
  3. ejb Stateless(name = "HelloWorldEJB", mappedName="HelloEJB") 应该只与 name 一起使用,因为它是可移植的,并且 mappedName 是供应商锁定的应该被劝阻,我只将它用于说明目的。
  4. 此外,我还没有在同一个容器中设置 jndi 道具。

Context context = new InitialContext();

  1. post 代码更改重新部署或重新启动 JBoss。

工作代码在粘贴下方 运行 ;)

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

我在上面post中保留了你的大部分代码。上面的客户端代码可以简化为

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