在 Tomee 中使用 OpenEJB 进行远程 EJB 查找

Remote EJB lookup using OpenEJB in Tomee

我正在尝试使用此处给出的示例

http://openejb.apache.org/hello-world.html

使用 OpenEJB 我可以输出 HelloWorld

我正在 Apache Tomee 中尝试同样的方法

我有这样的远程 EJB bean

@Remote
public interface Hello{
    public String sayHello();
}

@Stateless
public class HelloBean implements Hello{
    public String sayHello(){
        return "Hello World!!!!";
    }
}

装在罐子里

jar cvf hello.jar org

部署在 Apache Tomee 上

部署后的 Tomee 日志 hello.jar

03-Oct-2017 15:55:51.778 INFO [localhost-startStop-1] org.apache.openejb.assembler.classic.Assembler.createApplication Deployed Application(path=/home/ashish/apache-tomee-plus-7.0.2/webapps/manager)
03-Oct-2017 15:55:51.805 INFO [localhost-startStop-1] sun.reflect.DelegatingMethodAccessorImpl.invoke At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
03-Oct-2017 15:55:51.826 INFO [localhost-startStop-1] sun.reflect.DelegatingMethodAccessorImpl.invoke Deployment of web application directory /home/ashish/apache-tomee-plus-7.0.2/webapps/manager has finished in 137 ms
03-Oct-2017 15:55:51.831 INFO [main] sun.reflect.DelegatingMethodAccessorImpl.invoke Starting ProtocolHandler [http-nio-8080]
03-Oct-2017 15:55:51.839 INFO [main] sun.reflect.DelegatingMethodAccessorImpl.invoke Starting ProtocolHandler [ajp-nio-8009]
03-Oct-2017 15:55:51.845 INFO [main] sun.reflect.DelegatingMethodAccessorImpl.invoke Server startup in 5735 ms
03-Oct-2017 15:56:51.874 INFO [ContainerBackgroundProcessor[StandardEngine[Catalina]]] org.apache.openejb.config.ConfigurationFactory.configureApplication Configuring enterprise application: /home/ashish/apache-tomee-plus-7.0.2/webapps/hello.jar
03-Oct-2017 15:56:51.914 INFO [ContainerBackgroundProcessor[StandardEngine[Catalina]]] org.apache.openejb.config.InitEjbDeployments.deploy Auto-deploying ejb HelloBean: EjbDeployment(deployment-id=HelloBean)
03-Oct-2017 15:56:51.915 INFO [ContainerBackgroundProcessor[StandardEngine[Catalina]]] org.apache.openejb.config.AppInfoBuilder.build Enterprise application "/home/ashish/apache-tomee-plus-7.0.2/webapps/hello.jar" loaded.
03-Oct-2017 15:56:51.925 INFO [ContainerBackgroundProcessor[StandardEngine[Catalina]]] org.apache.openejb.assembler.classic.Assembler.createAppClassLoader Creating dedicated application classloader for hello
03-Oct-2017 15:56:51.926 INFO [ContainerBackgroundProcessor[StandardEngine[Catalina]]] org.apache.openejb.assembler.classic.Assembler.createApplication Assembling app: /home/ashish/apache-tomee-plus-7.0.2/webapps/hello.jar
03-Oct-2017 15:56:51.945 INFO [ContainerBackgroundProcessor[StandardEngine[Catalina]]] org.apache.openejb.assembler.classic.JndiBuilder.bind Jndi(name=HelloBeanRemote) --> Ejb(deployment-id=HelloBean)
03-Oct-2017 15:56:51.945 INFO [ContainerBackgroundProcessor[StandardEngine[Catalina]]] org.apache.openejb.assembler.classic.JndiBuilder.bind Jndi(name=global/hello/HelloBean!org.acme.Hello) --> Ejb(deployment-id=HelloBean)
03-Oct-2017 15:56:51.945 INFO [ContainerBackgroundProcessor[StandardEngine[Catalina]]] org.apache.openejb.assembler.classic.JndiBuilder.bind Jndi(name=global/hello/HelloBean) --> Ejb(deployment-id=HelloBean)
03-Oct-2017 15:56:51.969 INFO [ContainerBackgroundProcessor[StandardEngine[Catalina]]] org.apache.openejb.assembler.classic.Assembler.startEjbs Created Ejb(deployment-id=HelloBean, ejb-name=HelloBean, container=Default Stateless Container)
03-Oct-2017 15:56:51.987 INFO [ContainerBackgroundProcessor[StandardEngine[Catalina]]] org.apache.openejb.assembler.classic.Assembler.startEjbs Started Ejb(deployment-id=HelloBean, ejb-name=HelloBean, container=Default Stateless Container)
03-Oct-2017 15:56:51.988 INFO [ContainerBackgroundProcessor[StandardEngine[Catalina]]] org.apache.openejb.assembler.classic.Assembler.createApplication Deployed Application(path=/home/ashish/apache-tomee-plus-7.0.2/webapps/hello.jar)

现在我已经创建了 void main class 并尝试访问此 EJB

它抛出错误

我的主Class

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

public class HelloClient {

    public static void main(String[] args) throws Exception {
        Properties props = new Properties();

        props.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.openejb.client.RemoteInitialContextFactory");

    //props.put(Context.PROVIDER_URL, "ejbd://127.0.0.1:4201");


    //props.put(Context.PROVIDER_URL, "ejbd://localhost:8080");

    //props.put(Context.PROVIDER_URL, " http://localhost:8080/openejb/ejb");
        Context ctx = new InitialContext(props);
        Object ref = ctx.lookup("HelloBeanRemote");
        Hello h = (Hello) PortableRemoteObject.narrow(ref, Hello.class);
        String result = h.sayHello();
        System.out.println(result);
    }
}

使用:props.put(Context.PROVIDER_URL, "ejbd://127.0.0.1:4201");

run:
Oct 03, 2017 7:12:26 PM org.apache.openejb.client.StickToLastServerConnectionFactoryStrategy connect
WARNING: Cannot connect to server(s): 127.0.0.1:4201 Exception: 
java.net.ConnectException: Cannot connect to server 'ejbd://127.0.0.1:4201'.  Check that the server is started and that the specified serverURL is correct.
    at org.apache.openejb.client.SocketConnectionFactory$SocketConnection.open(SocketConnectionFactory.java:55)
    at org.apache.openejb.client.SocketConnectionFactory.getConnection(SocketConnectionFactory.java:35)
    at org.apache.openejb.client.ConnectionManager.getConnection(ConnectionManager.java:43)
    at org.apache.openejb.client.StickToLastServerConnectionFactoryStrategy.connect(StickToLastServerConnectionFactoryStrategy.java:70)
    at org.apache.openejb.client.StickToLastServerConnectionFactoryStrategy.connect(StickToLastServerConnectionFactoryStrategy.java:47)
    at org.apache.openejb.client.ServerMetaData.connect(ServerMetaData.java:57)
    at org.apache.openejb.client.Client.processRequest(Client.java:58)
    at org.apache.openejb.client.Client.request(Client.java:42)
    at org.apache.openejb.client.JNDIContext.request(JNDIContext.java:87)
    at org.apache.openejb.client.JNDIContext.lookup(JNDIContext.java:234)
    at javax.naming.InitialContext.lookup(InitialContext.java:417)
    at java8demo.HelloClient.main(HelloClient.java:25)

Exception in thread "main" javax.naming.NamingException: Cannot lookup '/HelloBeanRemote'. [Root exception is java.rmi.RemoteException: Cannot connect to any servers: Server #0: ejbd://127.0.0.1:4201]
    at org.apache.openejb.client.JNDIContext.lookup(JNDIContext.java:240)
    at javax.naming.InitialContext.lookup(InitialContext.java:417)
    at java8demo.HelloClient.main(HelloClient.java:25)
Caused by: java.rmi.RemoteException: Cannot connect to any servers: Server #0: ejbd://127.0.0.1:4201
    at org.apache.openejb.client.StickToLastServerConnectionFactoryStrategy.connect(StickToLastServerConnectionFactoryStrategy.java:66)
    at org.apache.openejb.client.ServerMetaData.connect(ServerMetaData.java:57)
    at org.apache.openejb.client.Client.processRequest(Client.java:58)
    at org.apache.openejb.client.Client.request(Client.java:42)
    at org.apache.openejb.client.JNDIContext.request(JNDIContext.java:87)
    at org.apache.openejb.client.JNDIContext.lookup(JNDIContext.java:234)
    ... 2 more
/home/ashish/.cache/netbeans/8.2/executor-snippets/run.xml:53: Java returned: 1
BUILD FAILED (total time: 0 seconds)

使用:props.put(Context.PROVIDER_URL, "ejbd://localhost:8080");

run:
Exception in thread "main" javax.naming.NamingException: Cannot lookup '/HelloBeanRemote'. [Root exception is java.rmi.RemoteException: Cannot open object output stream to server: ; nested exception is: 
    java.net.SocketException: Broken pipe (Write failed)]
    at org.apache.openejb.client.JNDIContext.lookup(JNDIContext.java:240)
    at javax.naming.InitialContext.lookup(InitialContext.java:417)
    at java8demo.HelloClient.main(HelloClient.java:25)
Caused by: java.rmi.RemoteException: Cannot open object output stream to server: ; nested exception is: 
    java.net.SocketException: Broken pipe (Write failed)
    at org.apache.openejb.client.Client.processRequest(Client.java:107)
    at org.apache.openejb.client.Client.request(Client.java:42)
    at org.apache.openejb.client.JNDIContext.request(JNDIContext.java:87)
    at org.apache.openejb.client.JNDIContext.lookup(JNDIContext.java:234)
    ... 2 more
Caused by: java.net.SocketException: Broken pipe (Write failed)
    at java.net.SocketOutputStream.socketWrite0(Native Method)
    at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:111)
    at java.net.SocketOutputStream.write(SocketOutputStream.java:155)
    at java.io.ObjectOutputStream$BlockDataOutputStream.drain(ObjectOutputStream.java:1877)
    at java.io.ObjectOutputStream$BlockDataOutputStream.setBlockDataMode(ObjectOutputStream.java:1786)
    at java.io.ObjectOutputStream.<init>(ObjectOutputStream.java:247)
    at org.apache.openejb.client.Client.processRequest(Client.java:104)
    ... 5 more
/home/ashish/.cache/netbeans/8.2/executor-snippets/run.xml:53: Java returned: 1
BUILD FAILED (total time: 0 seconds)

默认情况下,Tomee 不允许远程 EJB 查找

您需要在 Apache-Tomee/conf/system.properties 文件中启用它

// enable remote access 
 tomee.remote.support = true
 // blacklist none 
 tomee.serialization.class.blacklist = -
 // whitelist all classes or you can define your classes 
 tomee.serialization.class.whitelist = *

 openejb.system.apps = true
 openejb.servicemanager.enabled = true

更改这些配置后,重新启动 tomee 并部署您的 EJB 并且可以使用以下 url

访问所有 EJB
Properties p = new Properties();
p.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.openejb.client.RemoteInitialContextFactory");
p.put(Context.PROVIDER_URL, "http://localhost:8080/tomee/ejb");

final InitialContext ctx = new InitialContext(p);
Hello hbr = (Hello) ctx.lookup("HelloBeanRemote");

我这样做的另一个错误

我使用了来自 OpenEJb 容器的 openejb-client-3。0.jar

而不是 openejb-client-7.0.2.jar 来自 apache lib 文件夹

使用3版本以上的客户端jar