本地&远程访问一个EJB | 从开发角度看应用架构4

一、前言

本文仅代表作者的个人观点;

本文的内容仅限于技术探讨,不能作为指导生产环境的素材;

本文素材是红帽公司产品技术和手册;

本文分为系列文章,将会有多篇,初步预计将会有9篇。

二、对EJB的访问方式

EJB是一个包含在应用程序服务器上运行的业务逻辑的可移植组件。 如果客户端和EJB是同一应用程序的一部分,则客户端可以在本地访问EJB,如果EJB在远程运行,则客户端可以通过远程接口访问EJB。

如果客户端和EJB是本地的,也就是说,它们在相同的JVM进程中运行,则客户端可以调用EJB中的所有公共方法。 在EJB远程的情况下,必须提供一个远程接口,它是一个公开EJB业务方法的简单Java接口。 EJB类实现远程接口中的方法,其实现细节对客户端是隐藏的。

使用@EJB注释访问本地EJB

假设已经定义了如下的EJB:

@Stateless

public class TodoBean {

  public void addTodo(TodoItem item) {
  ...
  }

  public void findTodo(int id) {
  ...
  }
  ...
  }
...
}

客户可以通过使用@EJB注释将EJB直接注入到代码中来调用EJB上的方法:

public class TodoClient {  @EJB
  TodoBean todo;

  TodoItem item = new TodoItem();
  item.setDescription("Buy milk");
  item.setStatus("PENDING");

  //invoke EJB methods
  todo.addTodo(item);
...
}

访问远程EJB

在客户机在Java EE应用程序服务器的上下文之外运行的情况下,或者在应用程序服务器上运行的Java EE组件需要访问部署在远程应用程序服务器上的另一个EJB的情况下,可以使用JNDI来查找EJB。

为了确保远程客户端可以使用EJB,必须声明一个列出EJB业务方法的接口,并让EJB实现并覆盖这些方法。 例如,假设希望提供执行各种数学操作的EJB,请声明一个接口并列出如下所示的方法:

package com.redhat.training.ejb;public interface Calculator {

  public int add(int a, int b);
  public int multiply(int a, int b);
...
}

我们现在必须在EJB中提供这些方法的具体实现,并通过使用@Remote注释指出Calculator是EJB的远程接口:

package com.redhat.training.ejb;@Stateless@Remote(Calculator.class)

public class CalculatorBean implements Calculator {

  @Override
  public int add(int a, int b) {
    return a + b;
  }

  @Override
  public int multiply(int a, int b) {
    return a * b;
  }
  ...
  }
...
}

我们的EJB现在可以打包并部署在应用服务器上,并可以为远程客户端提供服务。

三、使用JNDI查找远程EJB

Java EE标准为客户端指定了标准的JNDI查找方案来查找EJB。 示例如下:

/<application-name>/<module-name>/<bean-name>!<fully-qualified-interface-name>

application-name:应用程序名称是部署EJB的EAR的名称(没有.ear扩展名)。 如果EJB JAR没有在EAR中部署,那么这是空白的。 应用程序名称也可以在EAR的application.xml部署描述符中指定。

module-name:默认情况下,模块名称是EJB JAR文件的名称(不带.jar后缀)。 模块名称可以在ejb-jar.xml部署描述符中重写。

bean-name:要调用的EJB的名称(实现类)。

fully-qualified-interface-name:远程接口的完全限定类名。 包括完整的软件包名称。

考虑到上面的代码清单,假设EJB打包在名为calculator-ejb.jar的文件中,该文件被进一步打包到名为myapp.ear的EAR文件中。 客户端可以使用以下查找字符串查找EJB:

myapp/calculator-ejb/CalculatorBean!com.redhat.training.ejb.Calculator

在部署EJB时,应用程序服务器会在服务器日志中列出EJB的不同JNDI绑定。 下面的清单显示了如果将EJB打包并部署为JAR文件,而不是EAR文件,则显示JNDI条目:

INFO  [org.jboss.as.ejb3.deployment] (MSC service thread 1-2) WFLYEJB0473: JNDI bindings for session bean named 'CalculatorBean' in deployment unit 'deployment "calculator-ejb.jar"' are as follows:java:global/calculator-ejb/CalculatorBean!com.redhat.training.ejb.Calculator
java:app/calculator-ejb/CalculatorBean!com.redhat.training.ejb.Calculator
java:module/CalculatorBean!com.redhat.training.ejb.Calculator
java:global/calculator-ejb/CalculatorBean
java:app/calculator-ejb/CalculatorBean
java:module/CalculatorBean

使用JNDI命名机制查找远程EJB的示例JNDI客户机程序如下所示:

package com.redhat.training.client;

public class CalculatorClient {

  public static void main(String[] args) throws Exception {    String JNDI_URL= "myapp/calculator-ejb/CalculatorBean!com.redhat.training.ejb.Calculator";
    try {
      Context ic = new InitialContext();      Calculator calc = (Calculator) ic.lookup(JNDI_URL);
      System.out.println("Response from server = " + calc.add(1,2);
      ...
    }
    catch (Exception e) {
      // handle the exception
    }

  }
...
}

我们还需要在客户端程序的类路径中提供一个名为jndi.properties的文件,其中包含运行EJB的远程应用程序服务器的主机名,IP地址,端口和安全详细信息(如果安全用于远程访问)。

java.naming.factory.initial=org.jboss.naming.remote.client.InitialContextFactory
java.naming.provider.url=http-remoting://10.2.0.15:8080
jboss.naming.client.ejb.context=true

JNDI API的InitialContext是一个标准的Java EE通用构造,用于查找部署在应用程序服务器上的组件。 它使用一组属性在类路径中查找jndi.properties。 某些属性对所有应用程序服务器都是通用的,有些属性是针对每个应用程序服务器的。

四、实验展现

实验由两个Maven子项目组成,它们位于hello-remote目录下的主项目文件夹下,其中包含hello-remote-ejb和hello-remote-client。

hello-remote-ejb项目在JBoss EAP中安装可远程访问的EJB,以便通过JNDI查找可用于外部客户端。 hello-remote-client项目是远程访问(从另一个JVM)EJB的Java SE应用程序。

首先,在JBDS中import已经存在的maven项目:

接下来,再import client:

查看hello-remote-ejb的pom.xml:

在源码的如下部分, 使用maven-ejb-plugin为ejb打包:

package已被声明为ejb,这告诉Maven如何打包最终的可部署artifact:

查看业务接口:HelloRemote.java文件:

这是一个简单的Java接口,它带有一个公共方法sayHello(一个class),它接受一个字符串名称参数并返回一个字符串。 在使用EJB时,通常使用接口来定义可用的方法,而不考虑实现。

查看最终执行任务的类的源码:HelloBean.java文件。

注意到这个EJB类实现了HelloRemote接口的sayHello方法,并且注意到标记这个类为无状态EJB的@Stateless注解。

接下来,启动EAP:

接下来,通过运行以下命令来构建和部署EJB到JBoss EAP:

查看EAP日志,hello-ejb-remote.jar已经被部署到EAP中:

JBoss EAP要求将EJB绑定在java:jboss / exported / *名称空间下,以允许外部客户端查找和调用EJB。

注意到没有“导出的”JNDI绑定。 您需要为EJB提供一个远程接口,以便将EJB绑定在该名称空间下。

编辑EJB项目的实现类HelloBean.java以启用远程JNDI查找并重新部署应用程序。

编辑实现类HelloBean.java以启用远程JNDI查找。 将@Remote注释添加到您的实现类并保存该文件,在源码中增加以下两行:

重新编译和部署hello-ejb-remote:

再次观察JNDI绑定。 这次我们可以在JBDS Console选项卡中看到导出的JNDI绑定:

使用Maven将hello-remote-ejb构件安装到本地存储库中,以便在编译期间可供客户端项目使用:

接下来,查看hello-client项目的源代码,并更新它以使用JNDI查找HelloBean。

在JBDS左窗格的Project Explorer选项卡中展开hello-client项目,然后双击pom.xml文件。

单击pom.xml选项卡查看pom.xml,我们可以看到对hello-remote-ejb的依赖(需要远程调用它)依赖关系的类型是ejb-client。 这告诉Maven这个工件是用于代码编译的hello-remote-ejb工件中定义的EJB的客户端。

查看HelloClient.java源码,将下面突出的部分修改:

修改成如下样子:

更新jndi.properties文件(src/main/resources)以使用http-remoting来访问在本地JBoss EAP服务器上运行的EJB。

将java.naming.provider.url属性设置为值http-remoting://127.0.0.1:8080,如以下图例所示:

修改成:

接下来,编译并运行客户端:

最后一行的reponse说明客户端对ejb调用成功!

魏新宇

  • "大魏分享"运营者、红帽资深解决方案架构师
  • 专注开源云计算、容器及自动化运维在金融行业的推广
  • 拥有MBA、ITIL V3、Cobit5、C-STAR、TOGAF9.1(鉴定级)等管理认证。
  • 拥有红帽RHCE/RHCA、VMware VCP-DCV、VCP-DT、VCP-Network、VCP-Cloud、AIX、HPUX等技术认证。

原文发布于微信公众号 - 大魏分享(david-share)

原文发表时间:2018-06-12

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏零基础使用Django2.0.1打造在线教育网站

零基础使用Django2.0.1打造在线教育网站(提示):错误贴

努力与运动兼备~~~有任何问题可以加我好友或者关注微信公众号,欢迎交流,我们一起进步!

953
来自专栏程序员阿凯

Android Studio下的单元测试

1044
来自专栏图像识别与深度学习

《Android》Lesson22-数据存储

1496
来自专栏猿天地

spring-data-mongodb之环境准备(1)

来源:猿天地 链接:http://cxytiandi.com/blog/detail/1717 首先创建一个maven工程,添加spring-data-mong...

2689
来自专栏圣杰的专栏

ABP入门系列(9)——权限管理

源码路径:Github-LearningMpaAbp 完成了简单的增删改查和分页功能,是不是觉得少了点什么? 是的,少了权限管理。既然涉及到了权限,那我们...

4515
来自专栏用户2442861的专栏

Spring ApplicationContext 容器 FileSystemXmlApplicationContext

http://wiki.jikexueyuan.com/project/spring/ioc-container/spring-application-con...

491
来自专栏玩转JavaEE

初识Spring Boot框架

按:最近公众号文章主要是整理一些老文章,主要是个人CSDN上的博客,也会穿插一些新的技术点。 ---- 前面的铺垫文章已经连着写了六篇了,主要是介绍了Sprin...

3555
来自专栏闻道于事

Spring Boot设置上传文件大小

1370
来自专栏Java架构沉思录

如何优雅实现Spring Boot自动配置

本文主要介绍如何把一个Spring项目(特别是一些公共工具类项目),基于Spring Boot自动配置的思想封装起来,使其他Spring Boot项目引入后能够...

673
来自专栏JavaNew

Spring Boot实战:静态资源处理

1794

扫码关注云+社区