Apache Geronimo 服务器的最新版本 M5(即 Milestone 5,参见 参考资料 中的链接),使用 CORBA 对与外部系统的互操作性进行了改进。如果您曾经接触过 CORBA,就会明白这种能力的重要意义,以及在特定项目中对 J2EE 服务器生存能力的影响。
CORBA 不但是很多遗留计算系统 —— 从大型机到超级计算机 —— 选择的外部接口机制,还作为一种分布式对象机制被大型的实时控制至关重要的电信业、银行业和国防系统广泛采用。这些系统中,很多时候需要访问 J2EE 服务器域中管理的信息和业务逻辑(或者相反)。要平稳地实现这种访问,而且不需要复杂的自定义编码,CORBA 和 J2EE 组件之间的互操作性是最基本的要求。
Geronimo 的 CORBA 互操作实现允许 CORBA 客户机应用程序访问 Enterprise JavaBeans? (EJB) 中包含的业务逻辑和 J2EE 业务层管理的数据。
本文示范了如何利用 Geronimo M5 的 CORBA 互操作能力。提供了一个完整的 CORBA 客户机访问 Geronimo 服务器管理的业务层 EJB 的例子。客户机利用了 Geronimo 客户机应用程序容器提供的支持。
CORBA 为分布式对象间的交互提供了基于标准的基础设施。它允许运行在不同硬件、不同操作系统上用不同编程语言编写的软件组件通过网络进行通信、协作和执行生产性任务。
CORBA 系统通过将对象之间的交互定义为明确的接口完成了这一不可思议的任务。要使用分布式对象的服务,必须通过接口与之交互。客户机不知道,也不需要知道接口是如何实现的,甚至是在何处实现的。图 1 说明了典型的 CORBA 系统的工作方式。
图 1. CORBA 中的对象交互
在 图 1 中,客户机代码通过接口使用服务器对象。事实上,接口是通过客户机本地的存根对象实现的。对客户机来说,它仅仅与本地的存根对象交互。在幕后,存根对象实现了和远程服务器对象同样的接口。客户机调用接口方法时,存根对象将调用转发给称为Object Request Broker (ORB) 的 CORBA 组件。客户机的调用代码不需要知道调用实际上是通过存根进行的。
ORB 是 CORBA 基础设施的关键一环。它负责本地化服务器对象(无论是否通过网络)然后把存根的调用发送到服务器。调用完成后,返回值通过网络返给 ORB,ORB 再交给存根。然后存根返回给客户机调用。对于客户机而言,存根对象就是接口的实现者。
在服务器端,ORB 也有重要的作用。它必须接收来自客户机 ORB 的方法调用,并转发给基干(skeleton)对象,后者和客户端的存根直接对应。从服务器逻辑的角度来看它隐藏了网络调用,即实现了接口。基干对象对服务器机器上实现接口的对象进行服务器端本地调用。
ORB 的具体实现细节因厂商而异。对于一家厂商来说,ORB 实现可能作为链接到客户机/服务器可执行文件的库实现。另一家则可能是库代码层和运行在同一机器上的守护进程之间的协作。无论如何,不同厂商的 CORBA ORB 都能够互相对话,这要感谢 CORBA Internet 通信协议 Internet InterORB Protocol (IIOP) 的标准化。图 1 说明了 ORB 通过 IIOP 通信的情况。
IIOP 是 General Inter-ORB Protocol (GIOP) 在 Internet TCP/IP 网络上的规范。从 CORBA 2.0 开始,该规范就要求不同厂商的 ORB 必须能够一起工作。目前,IIOP 广泛用于实现不同 ORB 实现之间、Java Remote Method Invocation (RMI) 和 CORBA 系统之间的互操作。
在 Java Development Kit (JDK) 1.4 及以后的版本中,可以选择使用 IIOP 协议在 Java RMI 对象之间通信。过去,只有私有的 Java Remote Messaging Protocol (JRMP) 用于 RMI。JRMP 和 IIOP 都用于通过网络发送消息调用信息或者返回数据。RMI 对象能够使用 IIOP 意味着基于 Java 的 RMI 客户机可以访问 CORBA 远程对象,CORBA 客户机也可以访问 RMI 实现的对象。对于让 Java 对象能够访问遗留的基于 CORBA 的资源,以及让其他 CORBA 客户机访问开放的 Java 服务器资源(如 EJB),这种互操作非常重要。
CORBA 系统中的对象完全通过接口来访问。在 CORBA 中,接口用一种标准格式 Interface Definition Language(接口定义语言,IDL)来定义,IDL 独立于具体的编程语言。图 2 说明了 IDL 如何将服务器对象和客户机结合在一起。
图 2. 从 IDL 生成存根和基干
对于支持的每种编程语言,都提供了生成原生语言绑定的工具。绑定 通常是用支持的编程语言生成的源代码(如 Java 绑定是 Java 代码,C++ 绑定是 C++ 源代码)。生成的代码然后被编译,并与客户机和源代码链接在一起。虽然绑定是文本源代码文件,与大多数生成的代码一样很容易修改,但是千万不要这么做,因为重新生成后会清除掉所有的修改。生成的代码包括客户端的存根(实现必要的接口)和服务器端的基干。还包括一些必要的 helper 方法,用于实现相应编程语言数据类型间的转换。
CORBA 体系结构提出了对象总线(object bus)的概念。通过 ORB 连接到该总线的任何客户机或服务器实现都可以交互和使用一组明确定义的、标准化的 CORBA 服务。图 3 解释了 CORBA 总线。
图 3. CORBA 对象总线
图 3 中,服务包括命名服务器、接口存储库(用于存储和检索接口及类型描述)和时间服务。
CORBA 中经常使用命名服务。对象管理组(即 OMG,请参阅 参考资料 中的 OMG 链接)规定了一种 Interoperable Naming Service (INS)。这种思想非常简单,与 RMI 类似。简而言之,服务器创建远程可访问对象的实例,使用 ORB 绑定它来接收发来的请求,然后使用众所周知的或者广为宣传的文本名将该实例的可用性注册到命名服务器。需要使用服务器上的服务的任何客户机都能够与命名服务联系,使用文本名称查找服务器来获得远程对象引用。
用 Java 编程语言编写代码时,J2EE 和 Java Naming and Directory Interface (JNDI) 的集成允许开发人员编写可处理不同目录和命名服务的对象查找代码。客户机代码调用 JNDI,JNDI 在底层通过提供程序实现转发到可用的服务。JDK 中提供了 CosNaming 提供程序,允许 JNDI 代码使用 CORBA 命名服务查找对象。图 4 说明了使用 JNDI 查找远程 CORBA 对象。
图 4. 基于 JNDI 的 CORBA 查找
图 4 还表明,与基于 JNDI 的 CORBA 查找一起使用时,RMI-IIOP 很容易让开发人员编制一个能同时用于 RMI 和 CORBA 服务器的代码库。
有了这些基本的了解后,现在可以看看如何实现 Geronimo 与外部 CORBA 客户机和组件的互操作了。图 5 显示了常见的几种互操作。其中包括:
- Web 层或 EJB 层 Java 客户机调用外部 CORBA 组件的方法。
- 通过 IIOP 公开的在 Geronimo 服务器中运行的 EJB 组件供基于 CORBA 的客户机远程访问。
- 应用程序客户机使用 Geronimo 客户机应用程序容器访问远程 CORBA 组件。
上述情况下,Geronimo 中的客户机或服务器代码都必须通过 IIOP 和 ORB 与外部 CORBA 组件通信。JDK 标准发行版带有 Sun Microsystems 的 ORB 实现,常常被称作 Sun ORB。Geronimo M5 利用这种 ORB 进行互操作。
图 5. Geronimo CORBA 互操作场景
使用 Geronimo,在部署的时候通过配置可以将 EJB 公开为 CORBA 服务器。这就是说 EJB 中不需要任何特殊的代码。事实上,任何已有的 EJB 都能公开为 CORBA 服务器对象。
我们的例子中,一个简单的无状态会话 bean 公开了一个方法来读取服务器端的时间戳。EJB 接口的代码如 清单 1 所示。
清单 1. 服务器时间戳无状态会话 EJB 的 EJB 接口
package com.ibm.dw.geronimo.corba; public interface ServerTimestamp extends javax.ejb.EJBObject { public String getTimestamp() throws java.rmi.RemoteException; } |
该 EJB 接口的具体实现在 com.ibm.dw.geronimo.corba.ServerTimestampImpl
类中,如 清单 2 所示。
清单 2. 服务器时间戳 EJB 的实现
package com.ibm.dw.geronimo.corba; import java.util.Date; public class ServerTimestampImpl implements javax.ejb.SessionBean { public String getTimestamp(){ return "This is the current server time " + new Date(); } private javax.ejb.SessionContext mySessionCtx; public javax.ejb.SessionContext getSessionContext() { return mySessionCtx; } public void setSessionContext(javax.ejb.SessionContext ctx) { mySessionCtx = ctx; } public void ejbCreate() throws javax.ejb.CreateException { } public void ejbActivate() { } public void ejbPassivate() { } public void ejbRemove() { } } |
注意,清单 1 和 清单 2 中都没有特殊的 CORBA 代码。事实上,即便 EJB 的部署描述符也非常普通。清单 3 显示了时间戳 EJB 的部署描述符 ejb-jar.xml。
清单 3. 服务器时间戳 EJB 的部署描述符 ejb-jar.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE ejb-jar PUBLIC '-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN' 'http://java./dtd/ejb-jar_2_0.dtd'> <ejb-jar> <enterprise-beans> <session> <display-name>Server timestamp Stateless Session Bean</display-name> <ejb-name>ServerTimestampEJB</ejb-name> <home>com.ibm.dw.geronimo.corba.ServerTimestampHome</home> <remote>com.ibm.dw.geronimo.corba.ServerTimestamp</remote> <ejb-class>com.ibm.dw.geronimo.corba.ServerTimestampImpl</ejb-class> <session-type>Stateless</session-type> <transaction-type>Container</transaction-type> </session> </enterprise-beans> </ejb-jar> |
清单 3 中普普通通的 ejb-jar.xml 可以让 EJB JAR 不需要修改就能部署在 Geronimo 或其他 J2EE 1.4 服务器上。
为了配置 EJB 让 CORBA 访问,需要为其创建一个专门的 Geronimo 部署计划。部署计划包含在 dp.xml 文件中。清单 4 显示了该计划文件的一部分,设置 EJB 以供 CORBA 客户机访问。
清单 4. 配置服务器时间戳 EJB 供 CORBA 访问
<?xml version="1.0" encoding="UTF-8"?> <application xmlns="http://geronimo./xml/ns/j2ee/application-1.0" configId="com/ibm/dw/geronimo/corba/ServerTimestamp" parentId="org/apache/geronimo/ServerCORBA"> <import> <uri>org/apache/geronimo/Security</uri> </import> <module> <ejb>dwcorba1-ejbs.jar</ejb> <openejb-jar xmlns="http://www./xml/ns/openejb-jar-2.0" configId="ServerTimestampEJB" parentId="org/apache/geronimo/ServerCORBA"> <enterprise-beans> <session> <ejb-name>ServerTimestampEJB</ejb-name> <jndi-name>ServerTimestampEJB</jndi-name> <tss-link>IdentityTokenNoSecurity</tss-link> </session> </enterprise-beans> </openejb-jar> </module> ... |
清单 4 中可以看到,我们把部署的 .ear 文件的父配置设为 org/apache/geronimo/ServerCORBA
配置。该配置文件包括标准org/apache/geronimo/Server
配置的全部内容,还有一些 CORBA 专用服务器端 GBeans 的定义。<tss-link>
元素用属性值IdentityTokenNoSecurity
指定了安全处理 GBeans 中的一个。下一节介绍该 GBean 的操作。
CORBA 2.3 CSIv2 安全需求的 GBean 实现
Geronimo 的 CORBA 实现和完全遵循 CORBA 2.3。CORBA 2.3 要求实现一个安全层,称为 Common Security Interoperability, Version 2 (CSIv2)。在通信之前,该层在 CORBA 客户机和服务器之间协商需要的安全级别。(在以后的文章中再详细讨论 CSIv2 的细节。)
Geronimo M5 中,CSIv2 特性是作为一组 GBean 实现的,可以在将 EJB 公开为 CORBA 访问时配置。
清单 4 中,<tss-link>
选择了一种 Target Security Service (TSS) 实现 GBean。它选择的是 IdentityTokenNoSecurity,这部署在 org/apache/geronimo/ServerCORBA 部署计划中,以允许不通过身份验证或加密来进行访问。
公开 EJB 供 CORBA 访问需要做的配置就这么简单。父配置 org/apache/geronimo/ServerCORBA 在模块启动时启动 CORBA 命名服务并将该 EJB 注册为可用的 CORBA 服务器对象。
要作为 CORBA 对象访问 EJB,需要创建一个简单的 GUI 客户机应用程序,运行在 Geronimo 应用程序客户机容器中。该客户机的源代码组件如表 2 所示。可以根据代码发行版交叉参考该表。
代码组件 | 说明 |
---|---|
TimestampDisplayClient.java | 客户机应用程序的主类,非常简单,构造 TimestampFrame 的实例并显示它。 |
TimestampFrame.java | JFrame 子类,使用 JDK 内置的 RMI-IIOP 访问远程 CORBA 服务器时间戳对象。它从远程 CORBA 服务器获得时间戳然后显示在自己的 Swing GUI 中。 |
SecurityCallbackHandler.java | Client Security Service (CSS) 处理 GBean 调用该处理程序。当服务器需要用户名和口令进行身份验证时,该处理程序通常显示一个用户界面来收集这些信息。这里的例子没有使用这个处理程序。 |
com.ibm.dw.geronimo.corba.ServerTimestamp.class com.ibm.dw.geronimo.corba.ServerTimestampHome.class | 正确地编译 TimestampFrame.java 需要这些 EJB Java 类文件。 |
TimestampFrame.java 的源代码如 清单 5 所示。这是调用远程 EJB/CORBA 对象方法的具体类。
清单 5. TimestampFrame.java 中的 RMI-IIOP 调用
package com.ibm.dw.geronimo.corba.client; import java.awt.BorderLayout; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.Vector; import javax.naming.Context; import javax.naming.InitialContext; import javax.rmi.PortableRemoteObject; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import com.ibm.dw.geronimo.corba.ServerTimestampHome; import com.ibm.dw.geronimo.corba.ServerTimestamp; public class TimestampFrame extends JFrame{ public TimestampFrame(String title) { super(title); } public void init() { JLabel timeStamp = new JLabel(getTime()); JPanel pane = new JPanel(); pane.setLayout(new BorderLayout()); pane.add(timeStamp, BorderLayout.CENTER); this.getContentPane().add(pane); } private String getTime() { String retval = ""; ServerTimestamp ts = null; try { Context ic = new InitialContext(); Object o = ic.lookup("java:comp/env/ServerTimestampEJB"); ServerTimestampHome home = (ServerTimestampHome) PortableRemoteObject.narrow(o, ServerTimestampHome.class); ts = home.create(); retval = ts.getTimestamp(); } catch (Exception ex) { ex.printStackTrace(); } return retval; } } |
清单 5 中,使用 InitialContext 通过 JNDI 查找来获得对象引用。得到的对象引用使用 PortableRemoteObject.narrow()
缩小转换为 EJB Home 接口。该代码可以通过 IIOP 访问远程 CORBA 对象和远程 RMI 对象。
与使用 IDL 生成的常规 Java 绑定(源代码)不同,Geronimo 可以动态生成二进制形式的 CORBA 存根。客户机应用程序会利用这种动态存根生成能力;存根是在请求 ORB 时生成的。
图 6 显示了对应用程序客户机和服务器端 EJB 可用的 Geronimo CORBA 支持。
图 6. Geronimo 的 CORBA 支持
应用程序客户机的部署计划中,配置了一个处理 CSIv2 客户端的 GBean,称为 CSS。deploy.xml 文件指定了和 NosSecurity 名关联的 CSS 实例。清单 6 说明了应用程序客户机需要的配置。
清单 6. 配置客户机应用程序进行 CORBA 访问
<module> <java>dwcorba1-clientapp.jar</java> <application-client xmlns="http://geronimo./xml/ns/j2ee/application-client" configId="client" clientConfigId="com/ibm/dw/geronimo/corba/ServerTimestampClient" clientParentId="org/apache/geronimo/ClientCORBA"> <import> <uri>org/apache/geronimo/ClientSecurity</uri> </import> <ejb-ref> <ref-name>ServerTimestampEJB</ref-name> <ns-corbaloc>corbaloc::localhost:1050/NameService</ns-corbaloc> <name>ServerTimestampEJB</name> <css-link>NoSecurity</css-link> </ejb-ref> <realm-name>client-properties-realm</realm-name> <callback-handler> com.ibm.dw.geronimo.corba.client.SecurityCallbackHandler </callback-handler> </application-client> </module> |
清单 6 中,客户机应用程序的父配置被设置为 org/geronimo/corba/ClientCORBA,该文件中配置了安全 GBean 实例。<ns-corbaloc>
元素告诉 Geronimo 客户机应用程序容器到何处寻找 CORBA 命名服务。<css-link>
标记指定了要使用的安全处理 GBean。<callback-handler>
标记指定了请求身份验证信息时 CSS GBean 使用的回调方法。
在 Geronimo 安装的 bin 目录中找到 startup.bat 文件。需要做一些修改,如 清单 7 中突出显示的代码。其中增加了一个必需的属性来指定 Geronimo ORB 支持类。(未来的 Geronimo 版本可能会简化该过程。)
清单 7. startup.bat 文件的修改
for %%z in (%CUR_DIR%) do set CUR_DIR=%%~sz set CORBA_OPTS=-Dorg.openejb.corba.UtilDelegateClass= com.sun.corba.se.internal.POA.ShutdownUtilDelegate -Dorg.omg.CORBA.ORBSingletonClass=com.sun.corba.se.internal.corba.ORBSingleton -Dorg.omg.CORBA.ORBClass=org.openejb.corba.sunorb.OpenEJBORB -Djavax.rmi.CORBA.PortableRemoteObjectClass= com.sun.corba.se.internal.javax.rmi.PortableRemoteObject -Djavax.rmi.CORBA.UtilClass=org.openejb.corba.util.UtilDelegateImpl @rem Set the path to the server.jar set SERVER_JAR="%~dp0server.jar" for %%z in (%SERVER_JAR%) do set SERVER_JAR=%%~sz :CheckServerJar ...... :StartServer echo on %JAVA% %CORBA_OPTS% -jar %SERVER_JAR% %ARGS% |
清单 7 中的选项必须作为连续的一行输入。将提供的 startup.bat 文件粘贴到 M5 bin 目录中可能更简单。使用这个修改后的 startup.bat 启动服务器。
本文还提供了构建该例子的 Ant 构建文件。需要根据 Geronimo 安装目录对 build.xml 作相应的修改。构建该项目使用下列命令:
ant ear |
然后可以在 dist 子目录中找到 dwcorba1.ear。要将包含 EJB 和客户机应用程序的 EAR 部署到 Geronimo 中,请在 Geronimo 安装目录中运行下列命令:
java -jar bin/deployer.jar --user=system --password=manager deploy dwcorba1.ear deploy.xml |
一定要将 dwcorba1.ear 和 deploy.xml 文件移动到同一目录中。
要运行客户机应用程序,请在源代码发行版中运行 runclient.bat 文件。该批处理文件按照和 startup.bat 相同的方式设置 ORB 支持属性,不过这一次是对客户机的 Java 虚拟机。runclient.bat 文件包含以下内容:
清单 8. Runclient.bat 文件代码
java -Djavax.rmi.CORBA.UtilClass=org.openejb.corba.util.UtilDelegateImpl -Dorg.openejb.corba.UtilDelegateClass=com.sun.corba.se.internal.POA.ShutdownUtilDelegate -Dorg.omg.CORBA.ORBSingletonClass=com.sun.corba.se.internal.corba.ORBSingleton -Dorg.omg.CORBA.ORBClass=org.openejb.corba.sunorb.OpenEJBORB -Djavax.rmi.CORBA.PortableRemoteObjectClass= com.sun.corba.se.internal.javax.rmi.PortableRemoteObject -jar bin/client.jar com/ibm/dw/geronimo/corba/ServerTimestampClient |
运行该客户机时,将在 GUI 中显示服务器的时间戳。该时间戳是从 CORBA 远程对象获得的,该对象实际上由远程 Geronimo EJB 处理。图 7 显示了客户机成功运行后的结果。
图 7. 显示服务器时间戳的应用程序客户机
本文介绍了如何集成异构的解决方案和利用已有的遗留系统投资,这是现代企业中经常面临的一项任务。CORBA 已经证明是一种有效的解决方案,已经部署在很多企业中。Apache Geronimo 组件与 CORBA 组件自由交互的能力,使得我们可以用最新的工具和编程方法论在现代 J2EE 平台上构建新的应用程序。
描述 | 名字 | 大小 | 下载方法 |
---|---|---|---|
Source code Geronimo CORBA example | code.zip | 300KB | HTTP |
学习
- 您可以参阅本文在 developerWorks 全球站点上的 英文原文。
- 请访问 The Object Management Group (OMG) 站点,这是最主要的 CORBA 信息和规范资源。
- 从 Apache Geronimo 官方项目站点 获得 Geronimo 最新的里程碑版本。
- 请阅读 “创建 Geronimo 客户机应用程序”(developerWorks,2005 年 6 月),了解如何使用客户机应用程序容器为 Geronimo 编写客户机应用程序。
- 请阅读 “利用 Geronimo 深入 EJB Web 应用程序”(developerWorks,2005 年 7 月),其中包含在 Geronimo 上使用 EJB 的一个简单例子。
- 请阅读 Damian Hagge 的 “企业中的 RMI-IIOP”(developerWorks,2002 年 3 月),从头了解 RMI-IIOP,看看 CORBA 和 RMI 能够多么好地配合。
- 在 developerWorks Geronimo 入门 可以找到适合新手和有经验用户的有用资料。
- 通过 IBM Support for Apache Geronimo 程序获得专家技术支持。
- 关注 Geronimo 的最新进展。Apache Geronimo 专家 Dave Klavon 定期更新 The Apache Geronimo Experience。
- 请访问 developerWorks Apache Geronimo 项目专区,这里提供了可以帮助您开始利用 Geronimo 进行开发的文章、教程和其他参考资料。
- 请访问 developerWorks developerWorks 开放源码专区,获得大量的 how-to 信息、工具和项目更新,帮助您使用开放源码技术进行开发并与 IBM 产品结合使用。
- 通过 developerWorks WebSphere 主页获得关于 IBM WebSphere? Application Server Community Edition 宣告的信息,以及关于其他 WebSphere 产品和技术的参考资料。
获得产品和技术
- 使用 IBM 试用软件 革新您的下一个开放源码开发项目,可以通过下载或从 DVD 中获得这些软件。
讨论
- 参与论坛讨论。
- Apache Geronimo 开发人员都聚集在 developerWorks 的 关注 Apache Geronimo 论坛。

Sing Li 是一位顾问和自由作家。他曾经参与 Beginning JavaServer Pages、 Professional Apache Tomcat 5、Pro JSP - Third Edition、Early Adopter JXTA、Professional Jini、 Beginning J2ME: From Novice to Professional, Third Edition 和其他书籍的编写。他还定期为技术杂志撰稿,也是 VON 和 P2P 发展的积极传道者。可以通过westmakaha@yahoo.com 与 Sing 联系。

研究过数学,从事过生物化学,做过大键琴制作者之后,David Jencks 又对软件工程发生了兴趣。他为多个开放源码项目作出过重要的贡献,包括 Jaybird 和最重要的 Geronimo。可以通过 david_jencks@yahoo.com 与 David 联系。