Tomee中的EJB容器远程调用

笔者在使用Tomee中EJB容器过程时发现,Tomee官方文档对EJB容器的远程调用的描述不够详细,同时网上的对EJB远程调用的资料也少之又少,本文旨在记录在使用Tomee中EJB容器远程调用过程中踩过的坑,以Tomee8.x为例。

Tomee官方文档:https://tomee.apache.org/tomee-8.0/docs/

1、前置步骤

修改Tomee配置文件system.properties,打开remote支持和设置白名单。

tomee.remote.support = true
tomee.serialization.class.blacklist = -
tomee.serialization.class.whitelist = *

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

2、server端

server端通过maven打成对应的war包,最终打包好的名称为:ejb-remote-server-demo.war

公共接口:

@Remote
public interface RemoteHello extends Serializable {

    String hello(String name);
}

 server端实现:

@Stateless(name = "statelessRemoteHelloServer")
public class StatelessRemoteHelloServer implements RemoteHello {

    private static final Logger log = Logger.getLogger(StatelessRemoteHelloServer.class.getName());

    private final String id = UUID.randomUUID().toString();

    @Override
    public String hello(String name) {
        log.info("stateless sever receive: " + name);
        return "hello client " + name + ", stateless response by " + id;
    }
}

 3、client端调用

client端调用分为三种:

1、server端和client端部署在同一个Tomee实例中,通过client调用server。

2、server端部署在一个Tomee实例中,client通过main函数进行调用。

3、server端和client端分别部署在不同的Tomee实例中,通过client调用server。

3.1、同一Tomee实例调用

关键点在于JNDI注入的时候,lookup的名称为java:global/ejb-remote-server-demo/statelessRemoteHelloServer,其中ejb-remote-server-demo是server部署后的包名,statelessRemoteHelloServer是server端RemoteHello接口实现的名称。

因为是同一个Tomee实例中,即使用的是同一个EJB容器,不需要指定EJB容器的远程地址,相当于同实例中的跨应用调用。

示例代码如下:

@Stateful
@WebServlet("/statelessClient")
public class StatelessRemoteHelloClient extends HttpServlet {

    private static final Logger log = Logger.getLogger(StatelessRemoteHelloClient.class.getName());

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) {

        String name = req.getParameter("name");
        try {
            InitialContext context = new InitialContext();
            RemoteHello remoteHello = (RemoteHello) context.lookup("java:global/ejb-remote-server-demo/statelessRemoteHelloServer");
            String res = remoteHello.hello(name);
            log.info("stateless server response: " + res);
            PrintWriter writer = resp.getWriter();
            writer.println(res);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

3.2、通过main函数调用

client通过main函数调用,不同JVM实例调用,需要指定EJB的context factory为org.apache.openejb.client.RemoteInitialContextFactory,provider.url为远程server端的EJB容器的地址,例如:http://localhost:8081/tomee/ejb

官方文档中给出的示例使用的provider.url为ejbd://25.14.3.92:4201,其中协议是ejbd,如果使用ejbd调用server端时,会提示以下错误:

Tomee在启动的时候输出日志会输出EJB容器的调用地址:

 官方remote ejb文档:https://tomee.apache.org/tomee-8.0/docs/remote-server.html

JNDI注入lookup查找名称 java:global/ejb-remote-server-demo/statelessRemoteHelloServer!com.example.RemoteHello,其中statelessRemoteHelloServer为server端RemoteHello实现类的名称,com.example.RemoteHello为RemoteHello接口的全限定类名。

示例代码如下:

    public static void main(String[] args) throws Exception{

        Properties p = new Properties();
        p.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.openejb.client.RemoteInitialContextFactory");
        p.put(Context.PROVIDER_URL, "http://localhost:8081/tomee/ejb");

        InitialContext context = new InitialContext(p);
        RemoteHello remoteHello = (RemoteHello) context.lookup("java:global/ejb-remote-server-demo/statelessRemoteHelloServer!com.example.RemoteHello");
        String res = remoteHello.hello("test");

        log.info("stateful server response: " + res);
    }

 3.3、不同Tomee实例调用

client端打成war后部署到Tomee中,通过servlet接口的形式调用,其中实现细节和main函数调用一致,不同的是JNDI注入lookup查找时名称不一样,可以通过global/ejb-remote-server-demo/statelessRemoteHelloServer!com.example.RemoteHello和statelessRemoteHelloServer两种方式都可以。

@WebServlet("/differentTomee")
public class DifferentTomeeInstanceServlet extends HttpServlet {

    private static final Logger log = Logger.getLogger(DifferentTomeeInstanceServlet.class.getName());

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) {

        String name = req.getParameter("name");

        try {
            Properties p = new Properties();
            p.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.openejb.client.RemoteInitialContextFactory");
            p.put(Context.PROVIDER_URL, "http://localhost:8081/tomee/ejb");

            InitialContext context = new InitialContext(p);
            // global/ejb-remote-server-demo/statelessRemoteHelloServer!com.example.RemoteHello
            // statelessRemoteHelloServer
            RemoteHello remoteHello = (RemoteHello) context.lookup("statelessRemoteHelloServer");
            String res = remoteHello.hello(name);
            log.info("stateful server response: " + res);
            PrintWriter writer = resp.getWriter();
            writer.println(res);
        } catch (Exception e) {
            log.severe("error: " + e);
            throw new RuntimeException(e);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值