级别: 初级 Sing Li (westmakaha@yahoo.com), 自由作家
2005 年 7 月 06 日 Geronimo 是服务器端运行环境,运行 JSP、servlet、EJB 和数据库,队列,并执行其他服务,Geronimo 在客户端提供了一个客户端应用程序容器,该容器可以减少客户端应用程序的设计和编码工作。本文将详细介绍该容器的作用,并展示如何在有和没有容器支持的情况下创建 Geronimo 客户端。
Geronimo 应用程序通常是基于 Web 的。Jetty 和 Tomcat 引擎是 Geronimo 的一部分,它们支持用 JavaServer Page、JavaServer Face、servlet 和其他模板技术或框架创建的基于 Web 的用户界面。用户通常使用标准 Web 浏览器访问该应用程序。通过浏览器访问的 Web 应用程序通常称为瘦客户机解决方案。
但是在许多情况下,基于 Web 的用户界面可能不合适。在这些情况下,可以使用 GUI 库(比如 AWT、Swing 或 SWT )在客户端创建代码。这些客户机应用程序通常称为胖客户机解决方案,仍访问由 Geronimo 托管的业务层 EJB 和 EIS 层服务,与其瘦客户机对应物一样。
本文向您介绍 Geronimo 客户机应用程序容器——一个 J2EE 1.4 组件,它可以显著降低创建胖客户机解决方案的复杂性。
您将学习客户机应用程序在 Geronimo 体系结构中的角色。我们将设计一个示例来展示如何用该容器创建和部署客户机应用程序。此外,本文还探讨了不使用客户机容器来创建访问 Geronimo 托管 EJB 的独立应用程序。
客户机应用程序容器的角色
Geronimo 客户机应用程序容器为客户端应用程序代码提供了标准 J2EE 环境。
该客户端编程环境与服务器端环境类似。但是,与服务器端 J2EE 模块在 Geronimo 服务中的托管环境下执行不同,客户机应用程序是在非托管环境下独立执行。客户机应用程序容器扩展了一些 J2EE API 和服务来用于客户机应用程序,但没有提供任何组件管理或托管设施。图 1 展示了运行中的客户机应用程序容器。
图 1. 运行中的 Geronimo 客户机应用程序容器
图 1 展示了两个具有访问单个 Geronimo 服务器的应用程序的客户机。这些机器上的用户可以使用标准 Web 浏览器访问托管 Web 应用程序。而且,每个客户机都有一个在客户机应用程序容器内执行的 Geronimo 胖客户机应用程序。这些胖客户机应用程序可以提供简单的命令行用户界面,或者更通常地,它们包含使用流行的客户端 GUI 技术创建的富用户界面。这些应用程序可以通过使用自己的 HTTP 连接连接回服务器来访问 Web 层,它们还可以通过 Geronimo 客户机应用程序容器的帮助来访问业务层和 EIS 层对象。
从图 1 可以看出,Geronimo 客户机应用程序容器:
- 在物理上与 Geronimo 服务器是分开的
- 运行在独立的 Java™ VM(或物理机)上,而非服务器上
- 提供了客户机应用程序的包装器
- 与 Geronimo 服务器通过网络通信
- 与服务器具有亲密的工作关系,为客户机应用程序提供了透明的引用解析、映射和依赖关系管理
J2EE 客户机解决方案可能包括瘦客户机、胖客户机和其他备选客户端访问技术。本文重点介绍胖客户机解决方案。参见侧栏 备选客户端访问技术 来了解其他可能的解决方案。
 |
备选客户端访问技术
当然,除了带有富 GUI 的 Java 客户机之外,还有其他技术可用于客户机应用程序上用户界面的实现。例如,Web 浏览器可以提供访问服务器资源的基于 Java Applet 的用户界面,或者 Java Web Start 可以从单个 URL 下载并运行完整的客户机应用程序。Geronimo 使用标准协议(比如 HTTP、HTTPS、CORBA 和 RMI)支持这些实现。客户机应用程序容器在这些备选解决方案中不起任何作用。
|
|
编写客户端 Java 应用程序时使用 Geronimo 客户机应用程序容器,可以简单地引用任何业务层对象,就像在服务器上编码一样。
例如,可以使用相同的 JNDI 上下文引用位于服务器上的 EJB,如同在服务器端编码 Web 应用程序一样(只要部署人员已经将 EJB 映射到部署描述符中的相同名称)。Geronimo 客户机应用程序容器解析 EJB 引用并远程访问 EJB,这些操作对于您是透明的。图 2 例示了客户机应用程序容器如何简化客户机应用程序编码。
图 2. 提供对服务器端对象无缝访问的客户机应用程序容器
 |
其他容器服务
结合服务器,客户机容器扩展了提供给客户机应用程序的许多其他服务(参见 图 2 中的虚线框)。一些例子包括安全性服务,比如登录/验证、服务器端依赖关系管理、消息驱动 Bean 的激活服务和 Web 服务查询。这些服务及其详细信息超出本文范围,但可能在以后的文章中进行介绍。
|
|
在图 2 中可以看到,客户机应用程序容器提供了带有 JNDI 的引用解析和映射层。该层提供对服务器端对象(比如 EJB)的无缝访问。在底层,客户机应用程序容器可以使用任何受支持的协议和传输(比如 JRMP 或 IIOP)与服务器通信。位于容器内的客户机应用程序不需要关心这些详细信息。事实上,应用程序部署人员可以在部署时更改 JNDI 名称映射和客户机/服务器通信的详细信息,而无需修改应用程序。
除 EJB 映射之外,客户机应用程序容器还为客户机应用程序提供了其他服务。有关详细信息,请参阅侧栏 其他客户机容器服务。
客户机应用程序打包
servlet 和 JSP 打包在 Web ARchive (WAR) 文件中,EJB 打包在 EJB JAR 文件中,而 J2EE 客户机应用程序打包在客户机应用程序 JAR 文件中。方便地,对于同一企业应用程序,客户机应用程序 JAR 文件可以与关联的 WAR、EJB JAR 和 RAR 文件放置在同一企业 ARchive (EAR) 文件中。单个 EAR 文件中可以有多个客户机应用程序 JAR 文件。把所有文件放在一个 EAR 文件中使发布、部署和维护变得简单。例如,可以将 EAR 部署在服务器上,以启动所有 EJB 和 Web 层组件,然后将相同的 EAR 部署在客户机应用程序容器上,并选择一个客户机应用程序以启动。图 3 展示了将客户机应用程序 JAR 文件打包在 EAR 文件中。
图 3. 将客户机应用程序档案打包在 EAR 文件中
客户机部署描述符和部署计划
文章“Geronimo! Part 2: Tame this J2EE 1.4 bronco”(developerWorks,2005 年 5 月)指出,Geronimo 中部署的 WAR 和 EJB JAR 文件必须包括关联的 J2EE 标准部署描述符,并可选地包括特定于 Geronimo 的部署计划。使用客户机应用程序容器的客户机应用程序档案的部署也遵守这个一般模式。表 1 描述了必需的部署描述符和可选的部署计划。
表 1. Geronimo 客户机应用程序档案的部署描述符和计划
|
文件名
|
是否必需?
|
描述
| |
application-client.xml | 是 | 标准 J2EE 部署描述符 | |
geronimo-application-client.xml
| 否,Geronimo 将使用默认值 |
特定于 Geronimo 的部署计划 |
如表 1 中提到的,如果不将 geronimo-application-client.xml 包括在档案中,则 Geronimo 使用默认值。默认值适用于多数情况,除非具有特殊的服务器端依赖关系、安全性或资源适配器要求。
独立 Geronimo 客户机
尽管 Geronimo 客户机应用程序容器具有通用性,但可能遇到一些不适合使用它的情况。例如,实际客户机应用程序可能是现有大型单片遗留系统的一部分,从而不能轻易分离和归档。在这种情况下,可能需要在没有客户机容器的帮助下创建客户机应用程序。这可以用 Geronimo 十分简单地实现。
图 4 例示了独立 Geronimo 客户机应用程序在不使用客户机应用程序容器时的操作。
图 4. 独立客户机应用程序操作
没有客户机容器的帮助,独立 Java 应用程序必须显式配置 JNDI 传输和通信协议来匹配由 Geronimo 服务器实例使用的相应协议。如果服务器配置更改,则必须修改该应用程序代码。因为应用程序将需要访问 EJB 和 Geronimo 通信协议,所以必须包括包含支持类的库。因为没有客户机应用程序容器,所以由容器扩展的任何附加服务都不可用于应用程序。尽管不是创建客户机的首选方法,但单独客户机通常可能是惟一可行的解决方案。
下面这个实践例子展示了如何编码应用程序客户机,首先使用 Geronimo 客户机应用程序容器,然后编码为独立应用程序客户机。
GUI 客户机示例
本例来自“Geronimo! Part 2: Tame this J2EE 1.4 bronco”中使用的 Really Big Pet Store 示例。将把简单的 GUI 客户机添加到企业应用程序中。这个简单的基于 Swing 的 GUI 客户机应用程序将访问业务层中的 CMP2 实体 EJB,并显示宠物店所有产品种类。
名为 CategoryBean 的实体 EJB 代表产品种类。相应的种类数据存储在 EIS 层的 RDBMS 中。有关设置 JDBC 连接器和 RDBMS 的信息,请参阅原文。 图 5 显示该版本的 0Really Big Pet Store 应用程序的底层原理:
图 5. GUI 客户机应用程序的结构和数据流
如图 5 所示,名为 CatClient 的 GUI 客户机驻留在客户机应用程序容器中。它访问服务器中的 CategoryBean CMP2 EJB,并调用它的 findAll() 方法来获得产品种类的列表。注意,原始 Really Big Pet Store Web 应用程序中的 StoreController servlet 由 Web 层中的 Jetty 托管,也通过名为 CategoriesBean 的无状态会话本地 EJB 访问。
该客户机应用程序有两个版本。
- 第一个版本运行在 Geronimo 客户机应用程序容器内,并使用它的 EJB 映射设施(如 图 5 所示)。
- 第二个版本是同一应用程序的独立版本。它直接访问 Geronimo 服务器,且不使用客户机应用程序容器。
编码 GUI 客户机
本例的第一个版本存档在 EAR 文件 reallybigpet.ear 中,该文件位于代码发行版的 dist 目录中。在部署 EAR 之前,必须确保查阅原始文章(参阅 参考资料)和 README 文件,以设置必需的 JDBC 连接器和 RDBMS 表。
CatClient 客户机应用程序打包在自己的 JAR 文件 bigpetstore-clientapp.jar 中。该 JAR 文件是 EAR 文件的一部分。该客户机档案的标准 J2EE 部署描述符是 application-client.xml,如 清单 1 所示。该描述符位于 JAR 文件的 META-INF 目录中。
清单 1. CatClient 应用程序的 client-application.xml
<?xml version="1.0"?>
<!--DOCTYPE application-client PUBLIC
"-//Sun Microsystems, Inc.//DTD J2EE Application Client 1.2//EN"
"http://java.sun.com/j2ee/dtds/application-client_1_2.dtd"-->
<application-client 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/applicationclient_1_4.xsd"
version="1.4">
<display-name>dW Geronimo Application Client Example</display-name>
<ejb-ref>
<ejb-ref-name>ejb/CategoryEntityBean</ejb-ref-name>
<ejb-ref-type>Entity</ejb-ref-type>
<home>com.ibm.dw.reallybigpet.ejb.cmp.CategoryHome</home>
<remote>com.ibm.dw.reallybigpet.ejb.cmp.CategoryRemote</remote>
</ejb-ref>
</application-client>
|
在清单 1 中,对服务器端实体 EJB 的引用在部署描述符中指定。Geronimo 服务器将基于本地和远程接口以及指定的 EJB 类型来定位实际的 EJB。该 EJB 的引用名称映射到 ejb/CategoryEntityBean。该映射可以在部署时通过部署人员进行配置。这层额外的映射允许使用固定的引用名称开发客户机应用程序,并在开发时灵活地映射到实际的 EJB。
客户机应用程序容器需要知道客户机应用程序 JAR 中的哪个类是要启动的类。因此,需要确保客户机应用程序 JAR 文件的清单具有一个主类,即项。在这个例子中,META-INF/MANIFEST.MF 文件中指定的主类是 com.ibm.dw.reallybigpet.client.CatClient:
Main-Class: com.ibm.dw.reallybigpet.client.CatClient
|
bigpetstore-clientapp.jar 不包括特定于 Geronimo 的部署计划——客户机应用程序不需要。由 Geronimo 提供的默认计划足够了。
使用客户机应用程序容器对远程 EJB 进行 JNDI 访问
在实际客户机代码 CatClient.java 中,使用下列步骤访问 EJB:
- 获得客户机应用程序容器提供的 JNDI 初始上下文
- 查找 java:comp/env 上下文,然后查找 ejb/CategoryEntityBean 项(注意该项对应于 清单 1 中的映射名称 ejb/CategoryEntityBean)
- 使用
PortableRemoteObject.narrow() 方法将返回的远程对象压缩为 EJB 本地接口的类型
- 使用 EJB 本地接口创建或提取 EJB 的实例,与服务器端的 EJB 编程方法一样
清单 2 展示了 CatClient.java 的代码。该类具有一个基于 Swing 的 GUI,它将显示 Really Big Pet Store 中所有可用的产品种类。在清单 2 中 CatClient.java 的 getCats() 方法中可以找到 EJB 查询代码。
在清单 2 中,getCats() 方法对 EJB 本地接口调用 findAll() 方法,并迭代通过返回的 CategoryRemote 远程实例来获得它们的 ids 和 names。该信息放置在 Vector 中。该 Vector 用在 init() 方法中以初始化 GUI 的 Swing JList。该 JList 将种类信息显示给最终用户。
创建客户机应用程序配置
现在可以尝试使用客户机应用程序容器的 CatClient。因为服务器正在运行,请确保在上次运行本例时未部署任何 reallybigpet 配置(使用部署人员的 list-modules 命令查看已部署的配置)。还要确保 PetsDB 配置(JDBC 连接器)已经配置且正在运行。
部署 reallybigpet.ear 文件,其中包括服务器端 EJB 和客户机应用程序 JAR,命令如下:
java -jar bin\deployer.jar deploy reallybigpet.ear
|
部署人员工具提示输入用户和密码。使用 system 作为用户,manager 作为密码。
要查看当前部署的设置,使用部署人员的 list-module 命令:
java -jar bin\deployer.jar list-modules
|
应该查看系统配置,以及服务器端 reallybigpet 配置和客户机应用程序配置,如下所示。客户机应用程序配置以粗体显示:
Found 22 modules
org/apache/geronimo/Tomcat
org/apache/geronimo/ActiveMQServer
org/apache/geronimo/J2EEDeployer
org/apache/geronimo/DefaultDatabase
org/apache/geronimo/SpringDeployer
org/apache/geronimo/Secure
org/apache/geronimo/DebugConsole
org/apache/geronimo/Server
org/apache/geronimo/DeployerSystem
org/apache/geronimo/ClientSystem
org/apache/geronimo/SystemDatabase
org/apache/geronimo/Client
org/apache/geronimo/Demo
org/apache/geronimo/SpringRuntime
PetsDB
org/apache/geronimo/InteropServer
org/apache/geronimo/SystemJMS
reallybigpet/bigpetstore-clientapp
reallybigpet
org/apache/geronimo/RuntimeDeployer
org/apache/geronimo/System
org/apache/geronimo/RemoteClassLoadingDeployer
|
因为特定于 Geronimo 的部署计划未包括在客户机应用程序 JAR 文件中,所以 Geronimo 为客户机配置使用了默认名称。该名称是使用已部署 EAR 文件名和客户机应用程序 JAR 文件名放在一起构造的。在这个例子中,客户机配置名称为 reallybigpet/bigpetstore-clientapp。
运行客户机应用程序容器
客户机应用程序容器的代码位于 bin/client.jar 中。要使用容器部署 CatClient 应用程序,请用客户机配置名称作为参数来启动客户机应用程序容器:
java -jar bin/client.jar reallybigpet/bigpetstore-clientapp
|
运行 CatClient 应用程序时,应该看到一个 Swing GUI,它具有一个列表,显示了 Really Big Pet Store 的所有产品种类(参见 图 6)。
图 6. 显示 CMP 实体 EJB 中的种类的 CatClient
在图 6 中,Swing JList 对应于 ID 显示了产品种类的名称。例如,带有 id 2 的突出显示的种类是 Clearance 种类。如果愿意,您可以更新 TDBMS 中的 petcats 表,当重新启动应用程序时,更新将显示在 JList 中。
编码独立客户机
没有客户机应用程序容器的支持,独立客户机必须对服务器端实体 EJB 执行自己的 JNDI 查询。清单 3 展示了独立客户机 CatClientStandalone.java 中的 getCats() 方法。
在 清单 3 中,JNDI 初始上下文是使用名为 org.openejb.client.RemoteInitialContextFactory 的自定义上下文工厂(一个 OpenEJB 特定包装器)构造的。URL 连接到端口 4201 的本地机,该端口是 EJB 网络服务器端口(参阅侧栏 关于 Geronimo 开发版本 以获得关于开发版本限制的信息)。当前版本的默认验证信息分别是 testuser:testpassword 。
 |
关于 Geronimo 开发版本
本文中的例子使用了最新不稳定版本,并已经在
SVN 版本 179212 (05/31/05) 和 169186 上进行了测试。最新不稳定版本的主要目的是便利开发和测试。同样地,设置 JNDI 的提供者 URL 信息以只访问本地机器(便于测试)。默认安全性政策也只接受来自本地机器的 EJB 协议连接。这就限制了
对环回设置的客户机测试——除非重新配置和重新构建服务器。在未来的
Geronimo 版本中,这些限制可能会得到改进。
|
|
不使用客户机应用程序进行操作
因为客户机应用程序容器不可用,所以不执行 java:comp/env 上下文的设置。此外,因为没有引用映射层,所以必须指定远程 EJB 的原 JNDI 名称。清单 3 中 EJB 的 JNDI 名称是 CategoryBean。可以通过为 EJB 指定 <jndi-name> 元素,在服务器上设置 Geronimo 使用的原 JNDI 名称。该元素在实体 EJB 的特定于 Geronimo 的 openejb-jar.xml 部署计划中 <enterprise-beans> 元素的 <entity> 子元素中指定。
没有客户机应用程序容器的支持,需要显式包括直接或间接引用的任何 Geronimo 或 EJB 类。这可能是一个相当大的列表。对于 CatClientStandalone 客户机,所需的库 JAR 文件包括:
- openejb-core-2.0-SNAPSHOT.jar
- geronimo-spec-j2ee-1.4-rc4.jar
- geronimo-kernel-1.0-SNAPSHOT.jar
- geronimo-security-1.0-SNAPSHOT.jar
- cglib-nodep-2.1.jar
您将需要以上全部的 JAR 文件(在 Geronimo 存储库和 lib 目录中),以及 EJB 接口类,比如 CategoryHome 和 CategoryRemote。源代码发行版(参阅 参考资料) 具有名为 sajar 的 ant 目标,该目标将创建 standalone-clientapp.jar 文件,绑定独立客户机应用程序与 EJB 接口。在 standalone 子目录中还有一个 run.bat 批处理文件,该文件将设置 classpath 以访问相关的库 JAR 文件。该批处理文件包含:
java -cp ./standalone-clientapp.jar;lib/openejb-core-2.0-SNAPSHOT.jar;
lib/geronimo-spec-j2ee-1.4-rc4.jar;lib/geronimo-kernel-1.0-SNAPSHOT.jar;
lib/cglib-nodep-2.1.jar;lib/geronimo-security-1.0-SNAPSHOT.jar
com.ibm.dw.reallybigpet.client.CatClientStandalone
|
注意,该批处理文件直接启动 com.ibm.dw.reallybigpet.client.CatClientStandalone 类,而没有调用 bin\client.jar 客户机应用程序容器。
测试独立客户机应用程序
在批处理文件正常工作之前,必须确保所有相关的 JAR 文件复制到 standalone\lib 目录中。
要试用该独立客户机,请使用 run.bat 批处理文件。它将启动客户机,从实体 EJB 中显示产品种类。得到的显示与 图 6 完全相同。
结束语
Geronimo 客户机应用程序容器将 J2EE 应用程序开发环境扩展到客户端应用程序。通过使用它,可以节省大量的开发工作,并享受 J2EE 1.4 容器灵活的部署时控制。当不能使用客户机应用程序容器时,仍可以使用 Geronimo 库来编码独立客户机应用程序以访问 Geronimo 服务器上的业务层对象。
下载 | 描述 | 名字 | 大小 | 下载方法 |
|---|
| Sample code tested on Geronimo build 179212 | code.zip | 1.3MB | HTTP |
|---|
参考资料
关于作者
对本文的评价
|