46.2. 使用应用客户端容器

这一节介绍如何使用RMI/IIOP协议访问应用服务器,和如何使用应用客户端容器开发和打包应用客户端。

46.2.1. 应用客户端容器简介

应用客户端容器是由一组Java类和必须的文件组成,它同客户端应用一起运行在客户端的Java虚拟机中,管理应用客户端组件的执行。象其他Java EE应用组件一样,应用客户端的执行依赖于客户端容器提供的系统服务。客户端容器和金蝶Apusic应用服务器通讯使用RMI/IIOP。和其他服务器端的Java EE容器相比,应用客户端容器可以说是相对简单的容器。

应用客户端容器提供的系统服务有:

  • 创建客户端运行环境,负责和应用服务器进行通讯。

  • 提供JNDI包装,使客户端能够使用“java:”名字空间。如其他J2EE 组件,应用客户端使用JNDI查找EJB,访问对资源管理器的访问、服务器被管理对象等等,应用客户端使用java:JNDI名字空间来访问以上这些内容。

  • 认证客户端。应用客户端容器自动完成JAAS用户认证。

另外,应用客户端不需要直接访问Java EE平台的事务功能。J2EE产品不需要提供JTA的UserTransaction对象给应用客户端使用。当然,应用客户端可以调用开始事务边界的EJB,并可使用JDBC API 提供的事务功能。但是当应用客户端调用EJB时开始了一个JDBC API 事务,事务环境不会传播到EJB 服务器。

应用客户端拥有所有的Java 2 Standard Edition 平台功能,每个应用客户端在客户端的Java虚拟机中运行。通过设置应用客户端JAR 文件中的manifest 文件的Main-Class属性,指定JAR文件中的Java类文件,运行时虚拟机查找Main-Class属性指定的类文件,执行其main方法(为准备容器环境,应用客户端容器在执行客户端程序之前运行, 安装SecurityManager,初始化名字服务客户端类库,等等)。

46.2.2. 开发应用客户端

EJB容器可以有多种不同的实现方式,但每一个容器都支持标准的EJB客户端视图。当开发客户端时,开发者通过home接口获得对EJB的访问,然后通过调用定义在远程接口中的方法,使用业务逻辑。这个简单的编程模型被应用到所有的EJB客户端。

使用EJB Home和远程接口

范例程序说明了客户端程序必须包含的内容:

  • 获得JNDI initial context。

  • 使用initial context获得EJB Home引用。

  • 通过调用EJB Home的create或find方法获得EJB实例引用。

  • 访问EJB的业务逻辑方法。

46.2.2.1. 定位Home接口

使用JNDI查找和定位EJB组件的Home接口。下面的代码描述了定位EJB组件Home接口的步骤:

//创建initial contenxt
Context initial = new InitialContext();
Object objref = initial.lookup("java:comp/env/ejb/Hello");
HelloHome home = (HelloHome)PortableRemoteObject.narrow(objref,HelloHome.class); 

46.2.2.2. 创建EJB实例

客户端调用HelloHome对象的create方法创建EJB实例。create方法返回Hello类型的对象。远程接口Hello定义了提供给客户端调用的EJB业务方法。

Hello hello = home.create();

46.2.2.3. 调用业务方法

开发者调用远程接口Hello上的业务方法,EJB容器将调用运行在服务器端的HelloBean实例上相应的方法。客户端调用sayHello业务方法的代码如下:

String str = hello.sayHello("apuaic");
System.out.println(str);  

46.2.3. 打包应用客户端

应用客户端被打包成JAR文件并且包含部署描述文件和MANIFEST.MF文件。部署描述文件是一个名为application-client.xml的xml文件,用于描述应用客户端所引用的EJB和外部资源。

application-client.xml文件必须符合application-client_1_4.xsd文档类型声明,并在文件中指定正确的schema:

version="1.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/application-client_1_4.xsd"

范例程序的客户端部署描述文件为,其中定义了EJB引用:

<?xml version="1.0" encoding="UTF-8"?>

<application-client version="1.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/application-client_1_4.xsd">
  <display-name>AppClient</display-name>
  <ejb-ref>
    <ejb-ref-name>ejb/Hello</ejb-ref-name>
    <ejb-ref-type>Session</ejb-ref-type>
    <home>samples.ejb.HelloHome</home>
    <remote>samples.ejb.HelloHome</remote>
  </ejb-ref>
</application-client>

应用客户端开始执行MANIFEST.MF文件中Main-Class属性指定的类的main方法,例如:

Manifest-Version: 1.0
Created-By: Apache Ant 1.5.1
Main-Class: samples.client.Client

应用客户端JAR文件结构如下图:

应用客户端JAR文件结构

46.2.4. 运行应用客户端

首先将应用客户端JAR文件和EJB JAR文件打包成J2EE应用,部署到Apusic应用服务器上。详细步骤请参考第 48.4 节 “打包和部署Java EE应用””。

然后使用Apusic提供的ejbGen工具生成可独立运行的应用客户端JAR文件:

java -classpath %apusic_home%/lib/apusic.jar com.apusic.tools.ejbgen.Main sample.ear appclient.jar

最后,在客户端容器中运行应用客户端:

java -classpath %apusic_home%/lib/apusic.jar
     -Djava.security.auth.login.config==login.conf
     com.apusic.client.Main -jar appclient.jar
[注意]注意

应用客户端运行在客户端容器中,会自动使用JAAS用户认证,因此需要提供LoginModules配置文件。配置文件中LoginModule的名字必须为“client”。客户端容器会自动使用名字为“client”的LoginModule进行JAAS用户认证。

如果使用apclient启动客户端容器,可以指定url参数,格式为:iiop://user:password@host:port,则不会弹出登录窗口。apclient使用$APUSIC_HOME/config/clientauth.cfg作为登录配置文件。也可以指定-noauth参数,以匿名身份访问服务器。

46.2.5. 不使用应用客户端容器

客户端可以不使用应用客户端容器,在获得初始化context时需要指定java.naming.factory.initial和java.naming.provider.url:

//设置初始化属性
Properties env = new Properties();
env.put("java.naming.factory.initial","com.apusic.naming.jndi.CNContextFactory");
env.put("java.naming.provider.url", "iiop://localhost:6888");
//获得 initial context
Context initial = new InitialContext(env);
//定位Home接口
Object objref = initial.lookup("ejb/appclientsample");

定位Home接口使用的JNDI名称为部署EJB时指定的JNDI名称。

[注意]注意

初始化context factory的类名为:

com.apusic.naming.jndi.CNContextFactory

Provider URL的格式为:

iiop://<host>:<port>

46.2.6. 关于范例

本节中的范例位于金蝶Apusic应用服务器安装目录中的docs/samples/client/rmi-iiop目录。

有关范例的内容、编译、部署与运行,可参考docs/samples/client/rmi-iiop目录下的readme.txt文件。