Geronimo 是一个 Apache Software Foundation 的开源 J2EE 1.4 服务器,诞生于 2003 年。在这篇由两部分组成的系列文章的第 1 部分 中,作者从系统设计角度描述了 Geronimo,分析了其架构,探讨了一些关键的结构概念,同时还介绍了一些基本的用户术语。现在,我们将继续这次 Geronimo 之旅,探讨服务器的部署、配置和管理能力的一些细节。
您想了解这个万能的容器在日常开发活动中能为您做些什么吗?首先看一个并不简单的企业应用程序的例子,您将用 Geronimo 的部署工具部署并控制许多标准 J2EE 可部署模块的生命周期。并使用 Java ServerPages(JSP)、servlet 和 Web 归档文件(WAR)中的一个标签库、企业归档文件(EAR)中的一个会话 EJB、资源归档文件(RAR)中的一个 Java Database Connectivity(JDBC)连接器以及一个使用包装在 EAR 中的 EJB Query Language(EJB-QL)的容器托管持久性(CMP2)实体 bean 来测试 Geronimo。您将了解 Geronimo 中的类加载器层次结构,以及它与配置的密切关系。最后,将介绍 Geronimo 支持可管理性的实际应用。用 Java Management Extensions(JMX)控制台可以查看 Geronimo 内部,并查看已经部署好的 Web 组件。
我衷心感谢 Geronimo 团队的 Geir Magnusson、Jr.、Jeremy Boynes、David Jencks 和 Alan D. Cabrera 对本文初稿所提的宝贵意见。
剖析 Geronimo
在 第 1 部分 对架构的讨论中,可以了解到,Geronimo 可以充当其他开源容器(如 Jetty、Tomcat 和 OpenEJB)的容器,提供配置、管理、部署和其他基本服务。
图 1 展示了 Geronimo 的洋葱式的容器嵌套。首先,Geronimo 本身是一个包装了像 Jetty 或者 Tomcat 这样的服务的容器。其次,Jetty 包装了已部署的 Web 应用程序组件(servlet、JSP、标签库等)。这里要注意的是,在每个容器边界,都需要有元数据或者部署描述符(XML 文件),如图 1 所示:
图 1. 切开的 Geronimo 洋葱展现了容器嵌套和所需的元数据

在图 1 中,j2ee-server-plan.xml 部署计划将告诉 Geronimo 如何部署和配置 Jetty 服务。剥到下一层,jetty-web.xml 部署描述符将告诉包含在 Geronimo 中的 Jetty 服务如何部署和配置 Web 应用程序组件。
当然,还需要包含那些在 J2EE 1.4 规范中规定的、标准的、独立于容器的部署描述符。其中包括 Web 应用程序的 web.xml、EJB archives 的 ejb-ear.xml 和 EAR 文件的 application.xml。
在本文中,我只将重点放在 J2EE 可部署模块的配置和部署上。系统组件(如 Jetty 和 Tomcat)的配置和部署不在本文范围内,尽管它们有类似的机制。
部署和生命周期控制
表 1 详细列出了不同的可部署文档、它们的部署描述符以及相关联的 Geronimo 部署计划。
表 1.
可部署文档及部署描述符和 Geronimo 部署计划
| 部署的文档 | J2EE 规范中的标准部署描述符 | 特定于 Geronimo 的部署计划 | |
Web application archive(WAR)文件 | WEB-INF 目录中的 web.xml | geronimo-jetty.xml | |
包含 EJB 的 JAR
| META-INF 目录中的ejb-jar.xml | openejb-jar.xml
| |
Enterprise Web application archive(EAR)文件 | pplication.xml,在所包括的所有 WAR 中都有一个 web.xml,在所有已包括的 EJB JAR 中,都有一个 ejb-jar.xml
| geronimo-application.xml | |
J2EE Connector resources archive (RAR)
| ra.xml | geronimo-ra.xml
| |
J2EE client application archive (JAR)
| application-client.xml | geronimo-application-client.xml |
有疑问的话,就解决它!
为了给服务器的用户提供最愉快的开箱即用体验,Geronimo 被设计为带有一组用于 WAR、EJB JAR 和 EAR 文件的默认部署计划。在很多情况下,这些内置的默认部署计划就足够用了,不需要创建特定于 Geronimo 的部署计划就可以部署大多数文档。
|
所有特定于 J2EE 的描述符(表 1 中的第二栏)必须嵌入到文档中。J2EE 规范(请参阅 参考资料)指定了每一种资源的位置,如图 2 所示(它只显示了服务器端文档)。不过,Geronimo 部署计划的位置可以有一些灵活性,图 2 中的虚线框表示一个可能的位置:
图 2. Geronimo 部署计划在 J2EE 可部署文档中的位置
 部署计划、配置和构建器
您可能对部署 Web 模块时,在 Geronimo 内到底发生了什么事情感兴趣。在 第 1 部分 中,曾介绍过,内核只处理配置。在开发的时候,可以调用了一个名为构建器的软件组件将 XML 部署计划和部署描述符转换为内核可以使用的部署描述符。在运行时,内核可以只处理得到的配置而不处理 XML。Geronimo 系统有许多专用的构建器。例如,通过处理特定于 Geronimo 的部署计划和描述 J2EE 部署描述符,EARConfigBuilder 知道如何为 J2EE 企业应用程序创建一个配置。
|
对照图 2 与表 1,就可以找出每一种归档文件的 Geronimo 部署计划。Geronimo 可以选择在什么地方放置这些部署计划: - 在文档内部,与相关联的部署描述符放在一起,如图 2 中的虚线所示。
- 在文档外部,像独立的 XML 文件那样,在使用部署工具来部署这个文档时,指定这个位置作为输入位置。
如果发现部署计划在文档外面,那么就不需要使用表 1 第三列中指定的名称,可以为该计划起任意名字。将部署计划放到文档外面有以下几点好处: - 文档文件本身通常是一般性 J2EE 文档,可以部署到任何兼容的服务器上。
- 可以很容易地进行更改部署计划,不需要提取、修改和重新归档部署计划。
- 可以使用编辑文件的工具,以图形方式修改文档。这个工具可以是一个兼容 JSR-88 的部署工具,甚至可以是一个自动化的系统托管代理。
使用外部部署计划的一个小缺陷是:如果没有自动工具,那么需要手工进行跟踪,以掌握相关的文档文件。
若想了解在部署一个 J2EE 模块时,Geronimo 中发生了什么,请参阅 部署计划、配置和构建器。
Really Big Pet Store 示例
了解了部署描述符与 Geronimo 部署计划之间的关系后,就可以在 Geronimo 上部署 Web 应用程序。在本文中,我使用的例子称为 Really Big Pet Store。它是一个电子商务应用程序的一部分,该应用程序将显示一个目录,并处理一个简单的购物车。这个商店不大,事实上,它很小。不过,这家商店卖的是很大的宠物。图 3 是这家商店的存货清单的一个示例: Figure 3. Really Big Pet Store 的存货清单
 我们将完成这个例子的三个版本,每一个版本都比上一个版本更复杂,并且使用不同的 J2EE 包来进行部署:
- 一个自成体系的 Web 应用程序。它包括 servlet、JSP 和一个 JSP 标签库,但没有使用任何外部资源。这一版本打包在一个 WAR 中。
- 第一个版本的修正版,它访问 EJB 来得到其产品目录信息。这个 EJB 是一个会话 bean,它有一个本地视图。该文档被绑定到一个 EAR 文件中。
- 进一步发展第二版,会话 EJB 成为一个实体 EJB 的 facade。这个实体 EJB 是一个符合 EJB2 的实体 bean,它用 CMP 访问关系数据库。应用程序绑定在一个 EAR 文件中。不过,它需要使用一个打包在 RAR 文件中的资源适配器 —— 一个 JDBC 连接器。关于 Really Big Pet Store 的源代码,请参阅 下载。
部署 WAR
这个例子的第一个版本打包在 reallybigpet.war 中,该文件位于发布代码的 war_only\dist 目录中。表 2 显示了这个版本的应用程序中的组件。后面的版本也使用所有这些组件,改变的地方会给出说明。
表 2. Really Big Pet Store Web 应用程序的组件
| 文件名 | 源代码位置(目录) | 说明 | |
StoreController.java | src | 一个 servlet,作为这个采用 MVC 模式的应用程序的前端控制器。这个控制器将收到的请求重定向到应用程序的两个 JSP 之一。以后,它还会访问 EJB 中需要的业务数据(通过 ReallyBigStore.java 间接访问),并将它们作为会话属性附加到表示层的 JSP 来进行显示 | |
ReallyBigStore.java
| src | 一个实用程序类,它提供了处理 JSP 标签库的静态方法。它还有一个帮助器函数,用于获取分类和货物信息。第一个版本生成自己的数据,新的版本通过访问 EJB 来获得信息 | |
bigpetstore.jsp
| jsp | 这是一个符合 JSP 2.0 的商店前端实现,显示可销售的所有货物。代码中完全没有嵌入式 Java 代码(无脚本)。代码中大量使用了 JavaServer Pages Standard Tag Library(JSTL)和自定义标签库
| |
checkoutcart.jsp | jsp | 这个 JSP 实现了进行订单结算的购物车的骨架。这段代码中没有 scriptlet,并且使用了 JSTL
| |
bigpetstore.css | jsp | 一个样式表,由应用程序中的两个 JSP 使用
| |
bigpetstore-taglib.jar
| WEB-INF/lib | 应用程序使用的自定义 JSP 标签库,用于在不使用后端 EJB 的情况下向应用程序提供数据
| |
Product.java, LineItem.java, Category.java
| src | JSP 用来处理宠物商店信息的 JavaBean |
用表 2 作为指南,您可以分析发行版本中的不同源代码文件,了解它们是如何工作的。在这里,主要关心的是在 Geronimo 上部署和运行这个应用程序。图 4 显示了部署应用程序后发生的事:
图 4. 在 Geronimo 上部署 Web 模块

在图 4 中,使用了 Geronimo 的部署器工具(也许还结合了 Geronimo 部署计划)将模块部署到目标服务器上。服务器将元数据保存在配置存储器中,将可执行代码存储在二进制储存库中。这样,不管由于什么原因终止服务器,都会使用同样的配置重启服务器。
进入 Geronimo 安装目录并输入以下命令启动 Geronimo:
还可以在命令最后加上配置的名称,以启动特定的配置(配置的定义请参阅 第 1 部分)。默认系统配置对于本例来说已经足够。可以使用下面的命令列出所有在这个配置中运行的模块:
java -jar bin\deployer.jar list-modules
|
该工具提示输入用户名和密码。用户名输入 system,密码输入 manager。注意使用部署工具列出模块。在发行版本中,还提供了一个批处理命令 lm.bat,该命令用于减少繁琐的键入。
要部署 reallybigpet.war 文档,首先将 Web 应用程序复制到 Geronimo 主目录中,然后使用以下命令:
java -jar bin\deployer.jar deploy reallybigpet.war
|
Geronimo 重要构建版本
在正式 1.0 版(和 J2EE 认证)之前,Geronimo 的二进制文件是作为重要构建版本(milestone build)发布的。每一个重要构建版本都引入了更多的功能。重要构建版本由字母 M 和一个数字表示,例如,第三个重要构建版本称为 M3 版本。下载和使用重要构建版本是获得相对更稳定的测试和试验版本的最好方法。仔细阅读每个重要构建版本的版本说明,了解还缺少哪些功能,或者哪些功能还不稳定。
|
还可以用批处理文件 dp.bat 减少一些键入。很快,部署工具就应当返回并报告部署已经获得成功。注意,在这里不需要使用单独的 geronimo-jetty.xml 部署计划。随 Geronimo 提供的 WAR 文件的默认计划在这里可以做得很好。如果再次执行 list-module 命令,将会看到运行的模块。默认名为 reallybigpet,它与 JAR 文件同名。
可以用 URL http://localhost:8080/reallybigpet/store.cgi 试验这个应用程序。
控制部署的模块的生命周期
回想一下,在 第 1 部分 中,GBean 可以选择性地通过 Geronimo 控制它们的生命周期。还可以用这项功能控制 Web 应用程序的行为。要停止这个应用程序,请使用以下命令:
java -jar bin\deployer.jar stop reallybigpet
|
如果在应用程序停止运行后访问商店 URL,那么 Geronimo 将不会作出响应。要再次启动它,请使用以下命令:
java -jar bin\deployer.jar start reallybigpet
|
要从 Geronimo 中完全删除这个模块的二进制文件和元数据,请使用以下 undeploy 命令:
java -jar bin\deployer.jar undeploy reallybigpet
|
解除部署这个模块后,如果还要使用它,则必须再次部署它。如果更新一个已经部署的模块,那么可以使用 redeploy 命令。它只使用一个步骤就有效地取消了对现有版本的部署,并部署了您指定的一个新版本。
部署 EAR
示例应用程序的第二个版本中加入了一个无状态的会话 EJB。控制器 servlet 通过访问这个 EJB 来获得将要显示的类别的列表。如果想分析源代码,请参阅 ejb 目录中的以下内容: - CategoriesHomeLocal.java 是 home 接口。
- CategoriesLocal.java 是 object 接口。
- CategoriesBean.java 是 EJB 的实现。
在 ejb-jar.xml 部署描述符中可以看到新会话 bean 的描述,如清单 1 所示:
清单 1. 无状态会话 bean
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ejb-jar PUBLIC '-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN'
'http://java.sun.com/dtd/ejb-jar_2_0.dtd'>
<ejb-jar>
<enterprise-beans>
<session>
<display-name>Categories Stateless Session Bean Local Interfaces</display-name>
<ejb-name>CategoriesEJB</ejb-name>
<local-home>com.ibm.dw.reallybigpet.ejb.CategoriesHomeLocal</local-home>
<local>com.ibm.dw.reallybigpet.ejb.CategoriesLocal</local>
<ejb-class>com.ibm.dw.reallybigpet.ejb.CategoriesBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
</session>
</enterprise-beans>
</ejb-jar>
|
StoreController 调用 ReallyBigPetStore 类中的 getCats() 方法来获得类别信息,并设置 cats 属性,如清单 2 所示。
清单 2. 提取用于 JSP 展示的业务数据
package com.ibm.dw.reallybigpet;
...
public class StoreController extends HttpServlet {
....
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
...
ArrayList cats = ReallyBigPetStore.getCats();
session.setAttribute("cats", cats);
...
}
...
}
|
ReallyBigPetStore 没有生成自己的数据,而是访问会话 bean 来取得类别信息。清单 3 显示了访问 EJB 的代码:
清单 3. 通过会话 EJB 获得分类数据
package com.ibm.dw.reallybigpet;
import java.util.*;
import com.ibm.dw.reallybigpet.ejb.CategoriesHomeLocal;
import com.ibm.dw.reallybigpet.ejb.CategoriesLocal;
import javax.naming.InitialContext;
import javax.naming.Context;
public class ReallyBigPetStore {
public ReallyBigPetStore() {
}
public static ArrayList getCats() {
CategoriesLocal cl = null;
try {
Context ic = new InitialContext();
Object o = ic.lookup("java:comp/env/CatEJB");
CategoriesHomeLocal ejbhome = (CategoriesHomeLocal) o;
cl = ejbhome.create();
} catch (Exception ex) {
ex.printStackTrace();
}
return cl.getCats();
}
}
|
WAR 文档的部署描述符现在需要引用这个会话 EJB。新的 web.xml 如清单 4 所示,其中包含增加的 ejb-local-ref 元素。
清单 4. 带有到本地会话 bean 引用的部署描述符
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app 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/web-app_2_4.xsd"
version="2.4">
...
<ejb-local-ref>
<ejb-ref-name>CatEJB</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<local-home>
com.ibm.dw.reallybigpet.ejb.CategoriesHomeLocal
</local-home>
<local>com.ibm.dw.reallybigpet.ejb.CategoriesLocal</local>
</ejb-local-ref>
</web-app>
|
获得最新的 Geronimo 版本
获得最新的 Geronimo 版本的最简单的方法是从 Geronimo 网站下载最新的非稳定版本(请参阅 参考资料)。 否则,如果喜欢冒险并有足够的版本控制系统的经验,那么可以检查存储库中的代码,编译绝对最新的 Geronimo 版本。这一过程更像是艺术而不是科学。您需要在系统中安装并运行 Subversion、CVS、Maven 和 Ant(请参阅 参考资料)。按照官方 Geronimo wiki 的说法,开发人员在大多数日子都会不断地添加代码更改,如果编译不成功,则需要以后再试。
|
EAR 的部署描述符 application.xml EAR 如清单 5 所示,它指定了 EAR 中的文档,并为应用程序提供了上下文根: 清单 5. 部署描述符为 EAR 提供了上下文根
<application
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_1_4.xsd"
version="1.4">
<module>
<ejb>bigpetstore-ejbs.jar</ejb>
</module>
<module>
<web>
<web-uri>reallybigpet.war</web-uri>
<context-root>/ReallyBigPetStore</context-root>
</web>
</module>
</application>
|
现在可以部署 reallybigpet.ear 了(在 dist 目录中,但要确保先取消对以前示例的部署)。
令人感到意外的是,即使文档包含位于 WAR 之外的 EJB,不创建其他 geronimo-application.xml 部署计划也可以让模块工作。原因是,Geronimo 会尽可能地协助部署。在解析引用时,它实际上是通过检查 home 接口和 object 接口来匹配 EJB。
在 RAR 中部署 TranQL 连接器
应用程序演变的最后一个版本中加入了另一个 EJB。这次,这个 EJB 是一个实体 EJB,它使用 CMP2 和 EJB-QL 访问关系数据库。这种外部依赖性让设置变得复杂了很多。
需要用适当的数据建立关系数据库。可以调整 addtab.sql 脚本来适应 RDBMS。清单 6 所示的这个脚本用于 MySQL 服务器:
清单 6. 向 CMP2 实体 EJB 提供表单的 SQL 脚本
drop table petcats;
create table petcats (
id varchar(20) NOT NULL,
name varchar(50) NOT NULL,
PRIMARY KEY (id)
) ;
INSERT INTO petcats VALUES( '1', 'New');
INSERT INTO petcats VALUES( '2', 'Clearance');
|
下一步,需要找到 RDBMS 的 JDBC 驱动,并将它复制到 Geronimo 的 repository 目录下的一个子目录中。例如,将这个例子中的 MySQL 驱动复制到 repository\mysql\jars 目录中。 要部署一个 JDBC 连接器,需要使用 TranQL 提供的连接器,它属于 Geronimo 的一部分。这个连接器提供连接池,并装载您所指定的驱动。要配置这个连接器,需要一个特定于 Geronimo 的部署计划,因为 Geronimo 无法猜测您使用哪一个 JDBC 驱动。请参阅 ddcmp 目录中的 geronimo-ra.xml 文件。清单 7 显示了这个文件的一部分:
清单 7. 部署 TranQL JDBC 连接器
<?xml version="1.0"?>
<connector xmlns="http://geronimo.apache.org/xml/ns/j2ee/connector"
version="1.5" configId="PetsDB" parentId="org/apache/geronimo/Server">
<dependency>
<uri>mysql/jars/mysqldriver.jar</uri>
</dependency>
<resourceadapter>
<outbound-resourceadapter>
<connection-definition>
<connectionfactory-interface>
javax.sql.DataSource
</connectionfactory-interface>
<connectiondefinition-instance>
<name>PetsDataSource</name>
...
</resourceadapter>
</connector>
|
在 geronimo-ra.xml 中,必须根据 JDBC 驱动的要求编辑入口项并配置连接器。注意这里对 PetsDB 的配置 ID 的用法。
现在就可以部署资源适配器了。请使用以下命令:
java -jar bin\deployer deploy repository\tranql\rars\tranql-connector-1.0-M4.rar
geronimo-ra.xml
|
需要查看 repository\tranql\rars 目录来了解将要使用的具体名称,因为在最新的重要构建版本中,它有了一些变化。(有关的更多信息,请参阅 Geronimo 的 重要构建版本 和 取得最新的 Geronimo 版本)。成功完成部署之后,可以执行 list-module 命令,查看 PetsDB 配置(模块)现在是否在运行。
尽管不建议对一般的应用程序使用 Derby RDBMS 实例,但是 Geronimo 系统仍然启动了这样一个实例(请参阅 参考资料)作为系统的默认数据源。可以这个例子中使用这个数据库实例。有关的更多信息,请参阅随源代码一同发布的 README.TXT。
Geronimo 配置和类加载器
在加入 Geronimo 部署计划之后,就可以指定配置 ID (configId 属性)和父元素的配置 ID(parentId 属性),就像在资源适配器的例子中那样。这样可以建立一个类加载器层次结构,使您能够在部署的不同模块之间共享代码。图 5 展示了一个配置层次结构:
图 5. 配置和类加载器

在图 5 中,配置 A 是配置 B 的父元素,配置 B 是一个包含 WAR 文件的 EAR 模块。白色的圈表示 Geronimo 类加载器(实际上是一个 URLClassloader)。在这里,配置 B 的类加载器是配置 A 的类加载器的子元素,这使得配置 A 中的代码可以被配置 B 访问。WAR 文件总是有自己的类加载器,以防止同一 EAR 中的其他代码访问 WAR 中的类。
部署 EAR 中的 CMP2 EJB
Really Big Pet Store 例子的最后一个版本使用一个实体 EJB 来获得其类别信息。会话 bean 现在访问新的实体 EJB 来获得类别信息。这个实体 EJB 的源代码在 ejbcmp 目录中: - CategoryHome 是 home 接口。
- CategoryRemote 是 remote 接口。
- CategoryBean 是 EJB 的实现。
映射 CMP2 EJB 的关键是 ejb-jar.xml 部署描述符,如清单 8 所示: 清单 8.
显示 CMP2 bean 映射和 EJB-QL 查询的部署描述符
<?xml version="1.0" encoding="US-ASCII"?>
<ejb-jar 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/ejb-jar_2_1.xsd"
version="2.1">
...
<enterprise-beans>
<entity>
....
<ejb-name>CategoryBean</ejb-name>
<home>com.ibm.dw.reallybigpet.ejb.cmp.CategoryHome</home>
<remote>com.ibm.dw.reallybigpet.ejb.cmp.CategoryRemote</remote>
<ejb-class>com.ibm.dw.reallybigpet.ejb.cmp.CategoryBean</ejb-class>
<persistence-type>Container</persistence-type>
<prim-key-class>java.lang.String</prim-key-class>
<reentrant>false</reentrant>
<cmp-version>2.x</cmp-version>
<abstract-schema-name>CategoryBean</abstract-schema-name>
<cmp-field><field-name>id</field-name></cmp-field>
<cmp-field><field-name>name</field-name></cmp-field>
<primkey-field>id</primkey-field>
<resource-ref>
<description>
This is a reference to a JDBC database.
</description>
<res-ref-name>jdbc/basic/entityDatabase</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
...
<query>
<query-method>
<method-name>findAll</method-name>
<method-params/>
</query-method>
<ejb-ql>
<![CDATA[SELECT OBJECT(a) FROM CategoryBean AS a]]>
</ejb-ql>
</query>
</entity>
</enterprise-beans>
</ejb-jar>
|
在清单 8 中,可以看到这个实体 bean 的持久存储字段的规格。同时,指定 findAll() 方法,使用 EJB-QL 从后端 RDBMS 提取所有类别。
为了正确部署这个实体 bean,需要创建一个 Geronimo 部署计划,即一个 openejb-jar.xml 文件,如清单 9 所示:
清单 9. Geronimo 部署计划,包括对部署的 TranQL 连接器的引用
<?xml version="1.0"?>
<openejb-jar
xmlns="http://www.openejb.org/xml/ns/openejb-jar"
configId="com/ibm/dw/ReallyBigPet"
parentId="PetsDB">
<cmp-connection-factory>
<application>null</application>
<module>PetsDB</module>
<name>PetsDataSource</name>
</cmp-connection-factory>
<enterprise-beans>
<entity>
<ejb-name>CategoryBean</ejb-name>
<jndi-name>CategoryBean</jndi-name>
<table-name>petcats</table-name>
<cmp-field-mapping>
<cmp-field-name>id</cmp-field-name>
<table-column>id</table-column>
</cmp-field-mapping>
<cmp-field-mapping>
<cmp-field-name>name</cmp-field-name>
<table-column>name</table-column>
</cmp-field-mapping>
<resource-ref>
<ref-name>jdbc/basic/entityDatabase</ref-name>
<application>null</application>
<module>PetsDB</module>
<name>PetsDBPool</name>
</resource-ref>
</entity>
</enterprise-beans>
</openejb-jar>
|
清单 9 给出了对部署的 PetsDB 连接器 的引用,并指定了将要映射的表和字段。注意,这个文件是 EAR 文件中的 EJB JAR 的一部分。为了方便起见,它与 JAR 打包到一起。 现在可以部署这个 reallybigpet.ear 应用程序的最后版本了。成功完成部署后,就可以试一试这个应用程序(用 URL http://localhost:8080/ReallyBigPetStore/store.cgi),看看从 RDMBS 提取的类别信息。 如要看对实体 EJB CategoryBean 下的数据库表进行更新的效果,请登录到数据库的命令行界面,并输入以下 SQL 语句:
INSERT INTO petcats VALUES( '3', 'Promotional');
|
现在,刷新浏览器,再试一次这个应用程序。您应当可以看到,在 JSP 显示的选项中,已经有了新添加的类别。
用 MC4J 窥探 Geronimo 的 JMX 结构内部
作为最后一步,下载并安装 MC4J JMX 控制台(请参阅 参考资料)并查看部署的 Web 应用程序所开放的属性和操作。
MC4J 已经通过 RMI 注册表支持 Geronimo 连接。从 Management 菜单中选择 Create Server Connection...。从 Server Connection Tppe 中选择 Geronimo,对于 Principle,输入值 system,对于 Credentials,输入 manager。图 6 显示了在 JMX 管理控制台中看到的 Really Big Pet Store 应用程序:
图 6. Geronimo 上部署的、通过 JMX 公开的企业应用程序

Geronimo 将部署的组件作为容器中的 GBeans 来管理(请参阅 第 1 部分)。除了通过 Geronimo 管理其生命周期,GBean 还可以公开那些可以通过 JMX 管理的属性和操作。这些属性和操作都是通过 JMX MBean 公开的。图 7 显示了如何通过这个 JMX 连接来公开应用程序的属性:
图 7. 通过 JMX 公开的企业应用程序组件

结束语
Geronimo 不是第一个开源 J2EE 1.4 容器,它可能也不是最后一个。但是它独特的“加入并参与”的邀请、它的优雅设计和大量可以免费获得的工业级、经过现场测试的 Apache 代码基,再加上全球开发团体的热心拥护,这些使得 Geronimo 有别于其他选择。像著名的 Apache Web 服务器项目一样,Geronimo 必将逐渐成长,达到其目标。这个项目是表明开源的 Java 开发已经最终成熟的一个重要标志。
参考资料 下载
| 描述 | |  | | Name | |  | | Size | |  | | Download method | |  | | Source code | |  | | j-geron2code.zip | |  | | 3.2 MB | |  | | FTP | |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
|