将JavaSwing应用程序连接到Geronimo服务器

创建可以与 Geronimo EJB 应用程序对话的独立客户端

简介

本文将展示如何开发可以与运行在 Geronimo 应用服务器内部的 EJB 应用程 序通信的独立(胖)客户端。基于我的前两篇文章 ——“将数据库连接到 Geronimo 应用服务器的三种方法”(developerWorks,2005 年 6 月)和“利 用 Geronimo 深入 EJB Web 应用程序”(developerWorks,2005 年 7 月)— — 本文向您展示一个连接到使用 Geronimo EJB 应用程序构建的小型电话簿数 据库的 Swing 客户端。您将阅读简要的设计说明,然后阅读有关运行该应用程 序所需的客户端库的信息。接下来我将介绍联系服务器并对服务器上远程无状态 会话 bean 执行操作的方法。最后,您将学习如何开发、编译并运行客户端应用 程序,以及如何配置服务器以允许来自网络中特定客户端的安全访问。

设计概述

首先简要介绍一下示例应用程序设计 —— 一个描述电话簿客户端应用程序 的统一建模语言 (Unified Modeling Language, UML) 部署图 —— 如 图 1 所 示。客户端应用程序通过其 EJB 端口连接到 Geronimo,并与 PhoneBook Session EJB 对话以通过 PhoneBook Entry Container-Managed Persistence (CMP) 操作数据库中的数据。

图 1. 电话簿客户端部署图

Geronimo 的默认发行版对 EJB 端口有限制。仅当客户端应用程序运行在同 一机器上并且通过环回地址(localhost 或 127.0.0.1) 连接时才能连接到该 端口。本文稍后的 配置 Geronimo 的 EJB 端口 一节提供了有关如何让其他机 器上的客户端访问服务器的详细信息。

用于连接到 Geronimo 的客户端库

要让客户端应用程序能够连接到 Geronimo 的 EJB 端口并与 EJB 层通信, 客户端类路径中必须要有下列 Java 库:

geronimo-spec-j2ee-1.4-rc4.jar

geronimo-kernel-1.0-SNAPSHOT.jar

geronimo-j2ee-1.0-SNAPSHOT.jar

geronimo-security-1.0-SNAPSHOT.jar

cglib-nodep-2.1.jar

openejb-core-2.0-SNAPSHOT.jar

从源代码编译 Geronimo 时,当您使用 Maven 构建脚本来编译电话簿客户端 应用程序时,这些库被放置到本地 Maven 资源库中且可供访问。您可以在 project.xml 文件的依赖关系部分中查看所有这些库位于 Maven 资源库的哪个 位置。

其中一些库在客户端与服务器的通信中起着非常重要的作用。Geronimo 使用 CGLib 库来执行动态代理生成。这使得服务器动态生成远程调用服务器端组件的 代码。如果在调试器中检查客户端上 InitialContext 对象的 lookup() 方法返 回的一个对象,可以看到动态生成的对象的类名包括 CGLib。geronimo-spec- j2ee.jar 文件包含所有的 Sun Java 2 Platform, Enterprise Edition (J2EE) 接口和类。没有该文件,客户端将无法理解任何动态代理实例。openejb- core.jar 文件是与服务器的 EJB 端口进行对话所必需的。用于在 Geronimo 服 务器中执行远程目录查询的 Java Naming and DirecTory Interface (JNDI) 类 就在该 .jar 文件中。最后的三个 .jar 文件提供了其他支持类,比如与 Geronimo 对话的安全主体。

执行远程会话本地查询

客户端通信部分的实现十分简单。将客户端连接到服务器时,Geronimo 与其 他任何 J2EE 服务器没有任何不同,遵守健全的通过 JNDI 查询和远程方法调用 (RMI) 进行的通信标准。JNDI 查询是获得对远程对象的引用的标准访问。要通 过 JNDI 进行连接,必须使用大量特定于 Geronimo 的属性来创建 InitialContext 实例,该实例用于执行查询。 清单 1 展示了有关如何创建会 话的示例。

清单 1. 创建到 Geronimo 托管会话 bean 的远程会话

import java.util.Properties;import javax.naming.Context;import javax.naming.InitialContext;import javax.rmi.PortableRemoteObject;public void Connect() {    String hostName = getHostName();   String port = getPort();   Properties props = new Properties();   props.setProperty ("java.naming.facTory.initial",          "org.openejb.client.RemoteInitialContextFacTory");    props.setProperty("java.naming.provider.url", hostName+":"+port);   props.setProperty("java.naming.security.principal", "username");   props.setProperty ("java.naming.security.credentials", "passwd");   Context ic;   try {      ic = new InitialContext(props);      PhoneBookSessionHome sessionHome = (PhoneBookSessionHome)          PortableRemoteObject.narrow(          ic.lookup(PhoneBookSessionHome.JNDI_NAME),          PhoneBookSessionHome.class);      phoneBookSession = sessionHome.create();   } catch (Throwable ex) {       ex.printStackTrace();   } finally {      if (ic != null) {         ic.close();      }   } }

如 清单 1 所示,创建了 Properties 对象并设置了四个属性。第一个并且 是最重要的属性是 java.naming.facTory.initial 属性,它必须设置为 org.openejb.client.RemoteInitialContextFacTory。其他属性指定提供者 URL 以及安全主体和凭证。提供者 URL 是用冒号隔开的主机名和端口。

前已提及,EJB 端口当前只接受从客户端连接到 127.0.0.1 或 localhost 的连接。默认端口是 4201。尽管如此,主机名和端口都可以进行配置。有关详 细信息,请参阅 配置 Geronimo 的 EJB 端口 一节。

创建好属性之后,就可以创建并使用 InitialContext 实例了。通过将属性 传递给构造函数完成这一操作。创建好实例之后,可以执行查询。清单 1 包括 一行复杂的代码,该行执行查询并对结果执行 PortableRemoteObject.narrow() 。对于向用户隐藏有关协议传输 —— RMI 或者可能是 Internet Inter-ORB Protocol (IIOP)—— 的详细信息,这是必需的。完成之后,远程会话就可供使 用了。在 清单 1 中,该行只创建了新 PhoneBookSession,并将其存储在一个 字段中以供将来使用。

具有对远程会话的引用之后,该引用可用于所有操纵电话簿数据库信息的操 作。现在只需要一个应用程序来练习该远程会话。

客户端的设计和开发

现在我们来深入研究一个小 Swing 应用程序的设计和开发,这个小应用程序 用来浏览、创建、删除和修改电话簿数据库条目。我尽量将 Swing 行话减到最 少,以防您比较熟悉的是另一种 GUI 技术,比如 Standard Widget Toolkit (SWT)。事实上,如果需要的话,应用程序架构已经使得将显示从应用程序内部 逻辑分离出来并将其连接到另一种 GUI 技术变得非常容易。

应用程序架构如 图 2 所示,这是一个详细显示应用程序静态结构的 UML 类 图。

图 2. 客户端应用程序的 UML 类图

图 2 中带绿色阴影的类是主要的应用程序类。Main 类是包含菜单和拆分窗 格(其左侧是 PhoneNumberListPanel,右侧是 PhoneBookEdiTorPanel)的框架 。该菜单还允许用户设置连接到哪个服务器的首选项,连接到服务器,并退出程 序。Application 类是一个单身类(singleton class),用作应用程序的所有 操作的控制器。它是惟一一个执行 EJB 操作的类,并保存对 PhoneBookSession 无状态会话 bean 的引用。

橙色的两个接口定义系统中的主要事件。每当 Application 决定电话号码列 表需要更新时,就会激活 DataChangeEvent。PhoneNumberListModel 注册该事 件。因为它是 PhoneNumberListPanel 中的主要数据模型列表视图,所以列表是 通过模型更改来更新的。这与 Swing 应用程序的设计方法一致。

PhoneNumberListPanel 和 PhoneBookEdiTorPanel 类都实现 PhoneBookSelectionListener 接口并注册来自 Application 单身类的事件。当 它们收到事件时,它们相应地更新当前的选择。如果是 PhoneBookEdiTorPanel ,当前选择导致 Name 和 Number 字段由来自当前选择的电话簿条目中的数据填 充。

如果希望节省编写用户接口代码的时间,通常可以在 Internet 上找到高质 量的免费工具。优秀的工具有 JGoodies Forms 1.0.5 和 FormLayoutMaker, FormLayoutMaker 是一个用于可视化创建窗体的小工具(参阅 参考资料 以获得 到这些工具的链接)。FormLayoutMaker 工具生成代表 JGoodies 窗体布局约束 的 XML 文件。这些工具帮助我快速创建了 Phone Number 编辑面板和 Preferences 面板的窗体。

构建应用程序

编译应用程序有两种方法。我使用 Eclipse Visual EdiTor (VE) 插件 1.2 版本在 Eclipse 中开发了该应用程序。它生成应用程序的大部分代码框架,但 它是以一种非入侵的方式完成的(没有代码标记和不可访问的代码块),所以如 果没有安装 VE 的话也应该没有问题。可以只加载项目并尝试运行它。

您可能需要设置 MAVEN_REPO 构建变量以指向本地 Maven 资源库。还需要构 建与本文一起提供的源代码中包括的 Geronimo 和 PhoneBook 服务器应用程序 (参阅 下载)。这是因为,要编译客户端应用程序,包含服务器应用程序中 EJB 接口的 .jar 文件必须发布到本地 Maven 资源库中。PhoneBook 的 Maven 构建脚本通过下列 Maven 构建脚本段完成该操作:

清单 2. Maven 构建脚本段

type="jar" project="${pom}"/>

用于构建应用程序的第二种方法就是使用 Maven 。在 PhoneBook 目录中解压文件并运行 maven 命令。然后在 PhoneBookClient 目录中进行相同操作。如果一切顺利,就已经在目标子目录中创建了 UberJar —— 一个包含运行客户端所需的所有内容的 JAR 文件。

两种构建方法运行得同样好。使用 Maven 方法的优点是如果您尚未下载依赖 关系,则它会自动从 ibiblio Web 站点(参阅 参考资料)上的远程 Maven 资 源库中下载这些依赖关系。所以如果 Eclipse 中的依赖关系有问题,就在项目 上至少运行一次 Maven 来校正缺少的库。

运行应用程序

确保 PhoneBook 服务器应用程序部署到 Geronimo 服务器中且正在运行。然 后键入下列命令:

java -jar phonebook-client-uber.jar

将会看到应用程序弹出,如 图 3 所示。

图 3. Geronimo 电话簿客户端应用程序

首先,从 File 菜单中选择 Connect。如果是连接到 localhost:4201 端口 ,则应该获得一个连接;否则,控制台窗口将会显示错误消息。可以通过选择 Edit > Preferences、更改信息并尝试重新连接来更改连接的服务器和端口 。一旦连接上之后,可以通过在电话号码编辑器中键入姓名和号码并单击 Save 来创建新记录。该记录将显示在姓名列表中。通过选择条目并单击 Delete 来删 除条目。通过选择条目、进行修改并单击 Save 来更改条目。

配置 Geronimo 的 EJB 端口

当前,配置 Geronimo 的 EJB 端口的方法需要编辑 XML 文件,然后重新编 译 Geronimo。Tom McQueeney 的大型 Geronimo Live blog 上的一篇短文清楚 介绍了如何使用 openejb/modules/assembly/src/plan/j2ee-server-plan.xml 文件更改 Geronimo Jetty 监听端口的详细信息(参阅 参考资料 以链接到该 blog)。同一文件还包含 EJB 端口的配置信息(参阅 清单 3)。

清单 3. j2ee-server-plan.xml 文件中的代码段

EJB4201127.0.0.1127.0.0.1HOST,NAME,THREADID,USERIDHOST,NAMEDefaultThreadPool ;openejb.server:name=EJBServer,*

您需要编辑 j2ee-server-plan.xml 文件并更改 allowHosts 属性。 Geronimo 支持许多不同类型的地址。必须用下列模式之一输入逗号分隔的地址 列表:

最后一格为 0 的 IP 地址。例如,192.168.10.0 允许 192.168.10 网络上 的任何机器与服务器通信。

任何完全指定的 IP 地址。

分解的 IP 地址。 这是一种特殊模式,允许指定地址的网络部分和以大括号扩住的主机地址列表。 例如,192.168.10.{5,6,7} 允许以下三个机器访问服务器:192.168.10.5、 192.168.10.6 和 192.168.10.7。

网络掩码 IP 地址。这是网络管理员熟悉 的一种地址。基于精确的位模式匹配规则(超出本文范围),IP 地址与网络掩 码相匹配。例如,192.168.255.255 允许 192.168.* 网络中的所有地址访问服 务器。

准确的 IPv6 地址。当将来的 IP 网络到来时,Geronimo 将准备好服 务,允许列出特定的 IP 地址。

网络掩码 IPv6 地址。

有关服务器接受的 特定模式的详细信息,请咨询源代码文件 —— ServiceAccessController.java —— 位于来源的 openejb/modules/core/src/java/org/openejb/server 目录 中。在此将会找到与支持的每个地址类型相匹配的明确的正则表达式。

对 j2ee-server-plan.xml 文件进行修改之后,重新编译并更新服务器部署 ,您将具有一个专门满足您需要的服务器。(如果只想查看针对同一机器上的服 务器运行的客户端,则无需这样做。默认情况下,Geronimo 被配置来完成这些 操作。)

结束语

本文提供了一个构建独立(胖)客户端的具体示例,该客户端可以与运行在 Geronimo 应用服务器内部的 EJB 应用程序进行对话。Geronimo 团队已经认真 实现了健全的标准,推广用简单的 JNDI 查询方法获得与无状态会话 bean 的远 程连接。如果只想让简单的应用程序运行,那么这是一个好消息,因为它只需要 您编写少量代码。

按照我所介绍的模式,您能够将许多比较大的数据库连接到与 Geronimo 服 务器位于同一机器上的客户端应用程序。使用本文提供的指示,您还能够配置 Geronimo 服务器以允许从连接到您的网络或 Internet 上的其他机器访问服务 器 EJB 端口。不妨尝试一下。

下载:http://www.ibm.com/developerworks/cn/opensource/os-ag- swing/

然后拍一些美得想哭的照片,留给老年的自己。

将JavaSwing应用程序连接到Geronimo服务器

相关文章:

你感兴趣的文章:

标签云: