级别: 初级 Roland Barcia (barcia@us.ibm.com), IT 咨询专家, IBM Software Services for WebSphere Saravana Chandran (sarachan@us.ibm.com), 高级软件顾问, IBM Software Services for WebSphere
2005 年 4 月 13 日 服务集成总线可用作企业消息传递的主干和面向服务的体系结构的关键组件。本文展示了如何通过 IBM® WebSphere® Application Server V6 轻松构建消息总线并部署应用程序,以及 IBM Rational® Application Developer 如何使开发人员能够创建和测试使用消息总线进行通信的 JMS 应用程序。
引言
大约两年前的一篇文章 使用 WebSphere Studio Application Developer 5.0 创建和测试消息驱动 Bean 向许多 WebSphere 开发人员介绍了在 WebSphere Studio 和 IBM WebSphere Application Server 中使用消息驱动 Bean (MDB) 的概念。后来 JMS 和 MDB 发展成了一项核心 J2EE™ 技术,为将松耦合组件构建到 J2EE 应用程序中提供了基础。JMS 和消息传递已成为异步“面向服务的应用程序”的基础。WebSphere Application Server V6 消息传递平台构建在服务集成总线 (SIB) 之上,它是企业服务总线 (ESB) 的一个实现,是将不同应用程序连接在一起实现组件之间无缝集成的一种新方法。
在本文中,我们将演示如何使用 IBM Rational Application Developer V6.0 和 WebSphere Application Server V6.0 来部署与测试消息驱动 Bean 和 JMS 应用程序,并且还将展示如何在 WebSphere Application Server 中配置服务集成总线来支持消息传递应用程序。此外,我们将使用 Rational Application Developer 来检查代码并为单元测试部署应用程序。在检查代码的同时,我们将突出显示 JMS 1.1 和 EJB 2.1 规范中的某些更新。
本文所提供的下载文件包括您将需要参考的资料。
导入并检查 JMS 和 MDB 应用程序
与以前的文章一样,我们将使用一个简单的“Hello”MDB 示例。虽然实际应用程序将以 XML 或 Java™ 对象(例如服务数据对象 (SDO))的形式交换更详细的数据,但这个示例非常简单,我们可以将主要精力放在 SIB 配置上。为了简单起见,我们将现有的 EAR 文件导入到 Rational Application Developer 中,并检查其 JMS 和 MDB 组件,而不使用向导创建应用程序。(使用 Rational Application Developer 向导创建 J2EE 组件非常简单,而且可获得许多有关这一主题的参考资料。)
导入 EAR 文件:
- 启动 Rational Application Developer,然后转到 J2EE 透视图。如果 J2EE 不是所列出的选择之一,则选择 Other => J2EE。(由于 Eclipse 3 lazy 初始化了插件,因此,这时可能提示您启用 J2EE 支持。)
- 从主菜单中选择 File => Import。这样将启动 File Import 向导。
- 选择 EAR File,然后选择 Next。
- 输入 EAR 文件名。如果已将下载资料解压缩到 C: 盘下,则目录将是 C:\WAS6ESB\MDBTest.ear。接受项目名的缺省值并确保为 Target Server 选中 WebSphere Application Server v6 。单击 Finish。(如果接收到关于未使用导入的警告,则可以忽略。您也可以在工作区首选项中的 Java Compiler Section 下禁用该警告。)
检查代码
EAR 文件非常简单,只包含一个 EJB JAR。EJB JAR 具有一个无状态会话 Bean,用于产生消息,而消息驱动 Bean 用于使用消息。图 1 显示了扩展模块以阐释组件的 Project Explorer 视图。
图 1. EJB JAR 模块和组件
首先,我们看一看 MyMDBBean Java 文件中的消息驱动 Bean。这是一个非常简单的消息驱动 Bean。清单 1 中的 onMessage() 方法只打印出消息。(通常,消息驱动 Bean 应该有更多的错误处理,但在这里,代码示例只是为了阐释。)
清单 1. MyMDBBean 消息驱动 Bean
/**
onMessage
*/
public void onMessage(javax.jms.Message msg) {
javax.jms.TextMessage txtMsg = (javax.jms.TextMessage)msg;
try
{
System.out.println("INSIDE MESSAGE DRIVEN BEAN: MESSAGE -> " + txtMsg.getText());
}
catch (JMSException e)
{
e.printStackTrace(System.out);
}
}
|
接下来,我们看一看 MessageProducerBean JavaNext 文件中的无状态会话 Bean。该无状态会话 Bean 使用 JMS 发送消息。代码如清单 2(为清楚起见,已删除了日志消息)所示。
清单 2. MessageProducerBean 无状态会话 Bean
public void publishMessage(String messageString) throws Exception
{
try
{
InitialContext context = new InitialContext();
ConnectionFactory cf = (ConnectionFactory)context.lookup
("java:comp/env/jms/MyConnectionFactoryRef");
Destination dest = (Destination)context.lookup
("java:comp/env/jms/MyDestinationRef");
Connection conn = cf.createConnection();
Session jmsSession = conn.createSession(false,Session.AUTO_ACKNOWLEDGE);
MessageProducer producer = jmsSession.createProducer(dest);
TextMessage message = jmsSession.createTextMessage();
message.setText(messageString);
producer.send(message);
producer.close();
jmsSession.close();
conn.close();
}
catch(Exception e)
{
logger.log(myLevel,ne.getLocalizedMessage(),ee);
mySessionCtx.setRollbackOnly();
throw e;
}
}
|
与该代码有关的重要一点是使用了新的 JMS 1.1 Unified API。在 JMS 的先前版本中,开发人员必须清楚地知道要使用哪一种消息模型:点到点还是发布/订阅。现在,我们不是在代码中直接使用队列和主题,而是使用通用基类(例如 Destination)来产生消息。然后在部署时或配置时选择消息传递模型。
检查部署描述符
要检查部署描述符,请按照以下步骤操作:
- 使用部署描述符编辑器打开 EJB 部署描述符(图 2)。
图 2. 打开部署描述符
- 转到 Bean Notebook 页并选择 MyMDB Bean。编辑器的右上部分显示了 EJB 部署描述符条目的去向。可以看到,MDB Bean 类型是消息驱动的,并且 EJB 使用容器管理的事务。
- 还有一个 Activity Configuration(图 3)部分。在 EJB 2.1 下,消息驱动 Bean 使用 J2C 1.5 入站连接器将 MDB 绑定到应用服务器。在 Activity Configuration 下,您可以为入站连接器指示特定的配置。例如,可在这里指定目的类型(队列或主题)。不过我们在示例中不指定这一信息,因为部署描述符是在开发时打包的。如果我们要指定它,那么就不能在配置时配置 MDB 来使用任一编程模型。在这里我们不指定目的类型,而是使用配置的激活规范配置来完成这一操作。
图 3. Activity configuration
- 转到部署描述符的 WebSphere Binding 部分。在 WebSphere Application Server V5 中,消息驱动 Bean 使用用于配置绑定的侦听器端口。而版本 6 中使用的是激活规范。(我们将在稍后部分配置一个激活规范。)激活规范在服务器上配置并指向特定的目的地。消息驱动 Bean 只需要指定激活规范的 JNDI 名称(图 4)。然而,您也可以自由指定目的地的 JNDI 名称,在这种情况下,在部署描述符中指定的目的地名称会覆盖在激活规范中指定的名称。(在这里还指定授权别名;在本例中不使用 WebSphere Application Server 安全性,但应该在实际应用程序中使用它。)如果部署描述符编辑器在 WebSphere Binding 下没有显示 JCA AdapterIf 部分,则右键单击 EJB 项目,然后选择 Properties => Server。
图 4. WebSphere 绑定
- 转到部署描述符编辑器的引用 Notebook 页。由于会话 Bean 使用 JMS JNDI 对象,所以需要进行引用(图 5)。
图 5. 引用 Notebook 页
- 要在配置时推迟消息传递模型,则 Connection Factory 引用类型应该是 ConnectionFactory,而非 QueueConnectionFactory 或 TopicConnectionFactory(图 6)。
图 6. Connection Factory 引用类型
- 目的引用使用 J2EE 1.4 中引入的称为消息目的引用的新引用类型(图 7)。在这里,我们指定该类型为 Destination,而非 Queue 或 Topic。消息目的引用还指定了使用目的引用的方法:产生消息或使用消息。该会话 Bean 为目的引用产生消息。消息目的引用就像任何其他 EJB 引用一样将 Bean 绑定到资源中,但是消息目的引用也可用来在相同的 EAR 中为多个 Bean 指定一个公共目的地。(有关详细信息,请参阅参考资料中的 EJB 2.1 规范(20.7 节))
图 7. 目的引用类型

 |

|
创建和配置服务集成总线
Rational Application Developer 包括 WebSphere Application Server V6 的完整基础版本。在这一部分中,我们将使用 WebSphere Application Server 管理控制台来配置服务集成总线。
服务集成总线 (SIB) 是一个逻辑概念。应用服务器(或集群)是总线的成员。作为同一总线的成员的所有应用服务器都共享一个公共基础设施,应用服务器可以在其中交换信息。图 8 阐释了这一逻辑概念。
图 8. 服务集成总线
实际上,作为总线一部分的所有应用服务器都在协作实现总线的功能性。当应用服务器成为总线的成员时,总线就自动配置了一个消息引擎来在应用服务器内实现其功能性。各种消息引擎协作构成了总线。我们的目标是配置应用服务器以支持消息传递应用程序,如图 9 所示。
图 9. 服务集成总线
 | | 对于发布/订阅来说,图稍有差别,我们将在其他文章中对此进行介绍,这里我们重点介绍点到点的情况。 |
|
图 9 显示了如何使消息引擎成为应用服务器的一部分:
- 将应用程序绑定到表示 JMS 提供程序的 JNDI 对象中。
- 将 JMS JNDI 对象绑定到消息引擎中的真实对象中。
- 点到点的目的地是队列。
- 消息引擎有自己的数据源,它用来存储永久性消息。
- 在单独的总线成员中配置队列,这意味着它们属于消息引擎。
消息引擎具有其自身数据存储的专用控件,因此其他消息引擎不能链接到它的数据存储。在 WebSphere Application Server ND 中,集群可以作为总线成员,在这种情况下,消息引擎非常有用,不过在这里我们主要介绍一些简单的情况,消息群集留待下一次研究。
现在我们将创建消息传递基础设施。
创建总线
创建总线相当简单:
- 在 J2EE 透视图中,通过选择服务器视图来启动服务器。右键单击服务器并从上下文菜单中选择 Start 。
- 启动服务器后,您可以右键单击服务器并选择 Run the Administrative Console,或者使用带有缺省管理控制台的浏览器 URL: http://localhost:9060/ibm/console。
- 使用任何 ID 登录到管理控制台,展开 Service integration 树,然后选择 Buses(图 10)。
图 10. 服务集成树
- 单击 New,为 Name 字段输入
MyBus,并接受其他字段的缺省值,然后单击 Apply(图 11)。
图 11. 总线配置
现在,我们已经成功创建了一个总线,如图 12 所示。
图 12. 服务集成总线
将应用服务器添加为总线的一个成员
通过选择总线成员,可以将我们的应用服务器添加到带有总线配置屏幕的总线中:
- 在 Additional Properties 选项卡上选择 Bus members(图 13)。
图 13. 其他属性
- 选择 Add => Server。
- 对于服务器,选择 <node_id>:Server1。对于数据存储,检查 Default。可以将任何支持的 JDBC 数据库作为消息引擎的数据源,但是,通过选择缺省值,WebSphere Application Server 会将内部的 Cloudscape® 数据库作为消息引擎的数据源。(图 14)
图 14. 添加新的总线成员
- 选择 Next,然后单击 Finish。
这时,我们已经隐式地在应用服务器中创建了一个消息引擎(图 15)。
图 15. 服务集成总线
创建队列目的地
现在,我们将在消息引擎中创建一个队列。通过这样做,我们将定义一个可用于总线的消息传递目的地:
- 选择总线来显示其配置页。在总线配置下的 Additional Properties 中选择 Destinations,然后单击 New。
- 选择目的地类型为 Queue,然后单击 Next(图 16)。
图 16. 创建新的目的地
- 在 Identifier 字段中输入
MyBusQueue,然后单击 Next(图 17)。
图 17. 创建新的队列
- 在图 18 中,通过选择承载队列的总线成员来将队列分配给特定的消息引擎。在本例中,缺省选择我们的服务器。选择 Next。
图 18. 将队列分配给总线成员
现在,我们已经在消息引擎中创建了一个队列目的地,如图 19 所示。
图 19. 服务集成总线
创建 JMS 资源
J2EE 应用程序将 JNDI 用作目录服务以按名称查找应用服务器资源。为了支持 JMS 应用程序,需要在总线中配置关于 JMS 资源的 JNDI。我们需要在 JNDI 目录中定义三个 JMS 资源引用:
-
连接工厂——由应用程序使用以连接到消息传递总线。
-
队列——由应用程序使用以发送和接收消息。
-
激活规范——由应用程序的消息驱动 Bean 使用以连接到队列并接受消息。
在接下来的步骤中,我们将创建这些资源引用并将它们添加到 JNDI:
- 在管理控制台中,选择 Resources => JMS Providers => Default messaging(图 20)。
图 20. 缺省消息传递
- 在 Connection Factories 选项卡中,选择 JMS connection factory(图 21)。请注意,我们使用的是通用的 JMS 连接工厂而不是特定的连接工厂类型。在 JMS 1.1 中,点到点和发布/订阅应用程序可以共享一个通用的连接工厂,以允许在它们之间进行单项事务处理。
图 21. JMS 连接工厂
- 单击 New。
- 在 Configuration Details 屏幕上,输入或选择以下值(图 22):
- Name:
MyConnectionFactory
- JNDI name:
jms/MyConnectionFactory
- Bus name:MyBus
接受其余的缺省值,然后依次单击 Apply 和 Save。
在 JMS 连接工厂中,有几个与连接池、消息持久性、路由和事务等相关的可用配置选项。有关详细信息,请参见 WebSphere Application Server V6 Information Center(参阅参考资料)。
图 22. 配置详细信息
接着,我们将创建 JMS 目的地:
- 在 Destinations 选项卡中,选择 JMS queue(图 23),然后单击 New。
图 23. JMS 队列
- 在 JMS 队列配置屏幕上,输入或选择以下值(图 24):
- Name:
MyMDBQueue
- JNDI name:
jms/MyMDBQueue
- Bus:MyBus(通过选择总线,总线的队列目的地会自动填充 Queue 名称字段。)
- Queue name:MyBusQueue
接受其余的缺省值,然后依次单击 Apply 和 Save。
图 24. JMS 队列配置
最后,我们需要为消息驱动 Bean 创建激活规范。激活规范有几个设置影响传递到消息驱动 Bean 的消息的行为,例如并行端点的数目。有关这些设置的详细信息,请参见 WebSphere Application Server V6 Information Center(参阅参考资料)。
- 在 Activation Specifications 部分,选择 JMS activation specification(图 25),然后单击 New。
图 25. JMS 激活规范
- 在 JMS 激活规范配置屏幕中,输入或选择以下值:
- Name:
MyActivationSpec
- JNDI name:
eis/MyMDBQueue_Act_Spec
- Destination type:Queue
- Destination JNDI name:jms/MyMDBQueue
- Bus:MyBus
- 接受其余的缺省值,然后依次单击 Apply 和 Save 以保存所有配置更改。
现在,我们已经为应用程序配置了所有可用的 JMS 资源(图 26)。
图 26. 服务集成总线
在继续下面的操作之前,从服务器视图中关闭并启动服务器以激活新的配置。
部署和测试 J2EE 应用程序
有几种方法可以将应用程序部署到 WebSphere Application Server;例如,使用管理控制台或通过脚本。由于处于开发的早期阶段并以单元测试为重点,因此我们将使用 Rational Application Developer 来直接部署应用程序。这便于直接从 Eclipse 工作台测试和调试应用程序。此外,我们还可以使用内置的 Universal Test Client 来测试 EJB 组件。
 | | 正如前面部分所述,在测试本文的 EAR 文件之前,您必须通过必需的连接工厂、目的地和激活规范来配置测试服务器。因此,在继续下面操作之前请确保已完成这一操作。 |
|
要部署 Rational Application Developer 应用程序,请执行以下步骤:
- 将应用程序添加到 WebSphere Application Server 测试服务器,方法是右键单击该服务器并选择 Add and remove projects(图 27)。
图 27. 添加和删除项目
- 在 Add and Remove Projects 对话框(图 28)中,选择 MDBTest 项目,选择 Add,然后单击 Finish。
图 28. 添加和删除项目
- 如果没有错误,则您已经成功部署了应用程序。MDB 和会话 Bean 将绑定到它们各自的 JMS 对象中,如图 29 所示。
图 29. 服务集成总线
在 Universal Test Environment 下测试应用程序:
- 在 J2EE 透视图的 Project Explorer 视图中,展开 MDBTestEJB。右键单击 MessageProducer 会话 Bean,然后选择 Run => Run On Server(图 30)。
图 30. 运行 MessageProducer
- 在 Server Selection 对话框(图 31)中,确保选中 Choose an existing server ,测试服务器高亮显示。同时选择 Set server as project default 以避免在随后的测试中出现这一提示。单击单击 Finish。
图 31. 定义新的服务器
- 启动 EJB 测试客户机后,将会弹出一个向导问您是选择 EJB 的 Local 还是 Remote Interface。请选择 Local。
- 选择并调用 Bean 的创建方法,如图 32 所示。
图 32. 调用创建方法
- 在结果部分选择 Work with Object ,然后选择对象的 publishMessage(String) 方法,如图 33 所示。
图 33. 选择发布方法
- 在 Value 字段中,输入测试消息的文本,例如
Test Message,如图 34 所示,然后按 Invoke。
图 34. 调用
- 成功创建方法后,请转到 Rational Application Developer 中的 Console 视图,您会看到消息驱动 Bean 已成功接收了消息(图 35)。
图 35. Console 视图中的消息
Universal Test Client 中的 JMS 实用工具
在 WebSphere Studio V5 中,有必要显式地创建一个 JMS 客户机来测试消息驱动 Bean,正如我们在本例中所做的。在 Rational Application Developer V6 中,Universal Test Client 现在已经有了 JMS 工具,允许您将消息发送到队列或主题的发布消息中(图 36)。如果愿意,您也可以使用该特性来测试样例 MDB。
图 36. Universal Test Client
结束语
消息传递是面向服务的体系结构的一个关键组件。考虑到这一点,本文展示了服务集成总线如何用作企业消息传递的主干、如何通过 WebSphere Application Server V6 轻松构建消息总线并部署应用程序,以及 Rational Application Developer 如何使开发人员能够创建和测试通过消息总线通信的 JMS 应用程序。
致谢
感谢 Wayne Beaton 和 Bobby Woolf 审阅和修改本文。
下载 | 描述 | 名字 | 大小 | 下载方法 |
|---|
| Download files | WAS6ESB.zip | 60 KB |
FTP | HTTP |
|---|
参考资料
作者简介
 | |  |
Saravana R Chandran 是位于北卡罗莱纳州 Research Triangle Park 的 IBM Software Services for WebSphere 的一位高级软件顾问。 |
对本文的评价
|