我们的场景包括通过 JMS 发送到后端应用程序的单向消息,指示包已提交给客户。我们将此映射为服务的“单向”操作(即操作具有请求,但无响应),并且向其提供了 JMS 绑定。接下来,我们将通过“请求-响应”操作(即每个请求有一个响应)介绍服务请求程序和提供程序之间的同步交互。我们的服务将使用 SOAP/HTTP 绑定作为其协议。与前面的示例一样,我们将通过 WebSphere ESB V6.0.2 实现的企业服务总线 (ESB) 路由每条消息,以分离服务请求程序和提供程序。服务请求程序和提供程序不知道消息流经 ESB,也不知道在 ESB 中路由或记录的任何消息。
您还将了解如何配置运行时,以便将消息路由到不同的端点地址,以及如何更改已记录的详细消息,二者都无需重新部署中介。在 WebSphere ESB 的管理控制台中可以直接设置此配置。此功能是该产品的 6.0.2 版本中的新增功能,自从第 2 部分发表之后,就发布了该版本。从本期开始,我们将在此系列文章的剩余部分中使用此产品的新版本。
本场景的业务背景需要 Posts-R-Us,才能使客户和雇员能够检索包提交的状态。为了能够使用各种客户机平台访问此功能,决定让其提供 Web 服务,该服务可以将包的跟踪号作为输入参数,并返回包含包状态(包括估计或实际交付日期)的 XML 文档。
此新增服务的每个请求都通过 ESB 路由,由 WebSphere ESB 中介模块表示。中介模块记录每个请求和每个响应消息,并将请求路由到实际服务逻辑的两个实现之一。要提高整个系统的灵活性,服务的两个实现必须存在,并且其中一个用作备份。请注意,在我们的示例中,我们不讨论在出现故障时应用服务器实例充当自动备份系统的集群环境,而是讨论该服务位于其他端点地址的第二个实例。 我们将向您介绍如何重新配置中介模块的导入绑定,以便在运行时使用 WebSphere ESB 管理控制台切换到备份服务。
和平常一样,中介流组件分别通过导出和导入与其客户机和实际服务提供程序通信。图 1 显示了系统的体系结构情况。
图 1. 示例场景的体系结构
对于本文的示例,我们需要实现一个服务提供程序,该提供程序将 trackingNumber 变量作为输入,并返回带有包信息的 packageStatus 结构。
对于本文稍后要向您介绍的一个测试而言,您必须确保正确配置了测试服务器。在 Servers 视图中,双击 WebSphere ESB Server v6.0,并确保选中 Run server with resources on Server(图 2)。在启动该服务器并将本文介绍的任何 EAR 应用程序存档部署到该服务器之前,您必须执行此操作。
图 2. 测试服务器配置
您可以在 PackageSatusServiceEAR.ear 文件中找到示例服务提供程序,它包括在本文提供的下载资料中。将此文件导入到 WebSphere Integration Developer V6.0.2,并为目标服务器选择 WebSphere ESB Server v6.0。只有使用其中安装了 WebSphere ESB 的相同 WebSphere Application Server 实例才能运行此服务;在实际的环境中,该服务大多数运行在独立服务器上。
在 J2EE 透视图中,您将看到名为 PackageStatusService 的新 Web 项目。请注意,它包含名为PackageTrackingService.wsdl 的 WSDL 文件,并且该文件中包含服务的定义。如果您在工具的 Interface Editor 中打开此 WSDL 文件,您可以看到它定义了名为 getPackageStatus 的请求-响应操作,如图 3 所示。
图 3. PackageTrackingService 接口
接下来,我们转到 postsrus.service 包中名为 PackageTrackingServiceSoapBindingImpl.java 的实际实现类。如果您在该工具的 Java 编辑器中打开此类,则可以看到在我们的示例中处理了两个跟踪号,即“123”和“456”。所有其他数字将导致异常。稍后在测试该场景时,我们将使用这些知识。
位于同一包中的其他有趣类是 PackageStatus.java,它包含作为服务操作调用结果返回的数据结构,它由以下四个属性组成:
package postrus.service; public class PackageStatus { private java.util.Calendar actualDeliveryDate; private java.lang.String location; private java.util.Calendar projectedDeliveryDate; private java.lang.String status; public PackageStatus() { } ... }
请注意,类型 java.util.Calendar 的属性表示交付时间和日期的方式。稍后将看到如何将其映射到 XML 模式中类型 <xsd:dateTime> 的元素。
现在,您可以简单地测试一下此服务,以确保它部署正确,并处于可操作状态。为此,请启动工具中的 WebSphere ESB 6.0.2 测试服务器,然后使用 Add and remove projects... 菜单选项将 PackageStatusServiceEAR 应用程序部署到该服务器。
部署并启动了应用程序后,您才能使用 WebSphere Integration Developer Web 服务测试工具。通过展开 Preferences 下的 Workbench => Capabilities 并选中 Web Service Developer,在 WebSphere Integration Developer 中启用 Web 服务功能。现在,右键单击 PackageStatusService.wsdl,然后选择 Web Services => Test with Web Service Explorer,如图 4 所示。
图 4. 选择 Web Services Explorer 选项
这将打开 Web Service Explorer 视图,您可以使用此视图测试 Web 服务,而无需实际生成测试客户机应用程序。
单击 getPackageStatus 操作链接,输入 123 作为跟踪号,然后单击 Go。测试服务器上的端口分配可以改变,所以,如果出现连接错误,请在 Web Services Explorer 中选择 PackageTrackingServiceSoapBinding,您可以添加另一个端点。尝试将端口设置为 9081,或看一下您的测试服务器设置,以确定正确的端口。在服务器控制台中,您应看到一个打印输出,指示调用了该服务和返回了 PackageStatus 对象(图 5)。
图 5. Web Services Explorer
接下来,继续进行操作,将 PackageStatusServiceBackupEAR.ear 文件导入到 WebSphere Integration Developer,并选择 WebSphere ESB 作为目标服务器。更改端点端口(如果需要)。此项目包含一组相同的 Java 类和其他构件,其中还定义了具有 getPackageStatus 操作的 Web 服务。换句话说,它是我们刚才查看的服务的正确副本;唯一的不同点是它部署在不同的端点地址下,并且使用不同的 System.out 语句指定已调用“备份服务”。
现在可以将此项目添加到 WebSphere ESB 服务器,并使用 Web Services Explorer 对它进行测试。这次请确保在 PackageStatusBackupService 项目中右键单击 WSDL 文件。运行测试后,在服务器控制台中,您应看到下面一行代码,它指示确实调用了备份服务:
[1/22/07 10:52:59:422 CST] 00000048 SystemOut O Package status request in backup service for tracking number 456
接下来,我们将介绍中介模块,该模块将用于我们刚才安装的服务提供程序和使用此服务的任何客户机之间。
我们将该模块存储为名为 PackageStatusModule.zip 的 Project Interchange 文件。导入该文件后,请切换到 WebSphere Integration Developer 中的 Business Integration 透视图。在 PackageStatusModule 模块中,您应看到位于 Interfaces 下的 PackageStatusService 文件。这是我们在服务提供程序中已经使用的同一 WSDL 文件。换句话说,中介模块将公开与原始服务相同的接口,所以无需在 ESB 中进行转换。请注意 Data Types 下方的 PackageStatus 定义,它具有从服务返回的字段。
现在,请在 Assembly 编辑器中打开模块的组装关系图。此组装没有什么特殊之处;它显示了中介流组件、一个导出和一个导入(图 6)。
图 6. 组装关系图
选择 PackageStatusServiceImport,并查看相关属性视图。在 Binding 选项卡中,您可以看到它指向您先前部署的服务实现的端点地址。请注意,端口号设置为 9082。如果测试服务器使用端口号 9081,您可以在此处的属性视图中更新它。类似地,如果您选择 PackageStatusExport,则会注意到其上有一项 Web 服务绑定,并附带一个新的端点地址。此地址是稍后测试完整的解决方案时您将在 Web Services Explorer 中使用的地址。
双击 PackageStatusMediation,打开 Mediation Flow 编辑器。由于您以前构建了中介流组件,所以此时并没有什么感到意外:通过 MessageLogger 中介元素路由每个请求和响应消息,以便将其记录在缺省数据库中。
图 7. 中介流组件
您可能记得,在 MessageLogger 元素的属性中,您可以定义 XPath 语句,以指示实际记录了消息的哪些部分。您可以在 Properties 视图的 Details 选项卡中对此进行更改。Root 属性的缺省值为“/body”,表示记录消息的整个正文。对于本示例,我们已将此属性更改为“/body/getTrackingStatus/trackingNumber”,表示仅记录实际数量。
这里,我们将开始使用 WebSphere ESB 版本 6.0.2 中的新功能,其名称为 promoted properties。在早期版本中,更改属性(如 MessageLogger 元素的 Root 属性)的唯一方法是将模块加载到 WebSphere Integration Developer、更改属性和将整个模块重新部署到服务器。使用版本 6.0.2,还可以在运行时通过管理控制台更改已“提升”的属性。在 Properties 视图中有一个新的 Promoted Properties 选项卡,您可以使用它选择希望更改的、特定于中介元素的属性。每个中介元素都有一组可以提升的特定属性。
在我们的场景中,您需要提升可让您定义记录消息哪些部分的属性。通过这种方式,您可以在运行时调整记录消息的数量,而无需重新部署模块。例如,假设您的服务具有非常大的消息有效负载。您可能决定仅记录该消息的一小部分以便节省存储空间。稍后,您可能需要对某些消息进行深入分析,为此,需要加载整个消息。现在,仅通过管理控制台就可以做到这一点。
在中介流中,打开 RequestMessageLogger 元素的 Properties 视图,并选择 Promoted Properties 视图(图 8)。
图 8. 提升的属性
请注意向每个提升属性提供别名的方式。这样,如果在同一模块中多个属性具有相同的名称,您可以在管理控制台中对它们进行区分。在此示例中,我们调用了属性 RequestMessageLogger.root。如果您在响应队列中检查一下 Message Logger 元素,您会注意到我们在此处提升了同一属性,但使用了其他别名,即 ResponseMessageLogger.root。具有相同别名的提升属性将共享相同的值。
现在,您可以部署中介模块并运行测试了。
下面将 PackageStatusModuleApp 添加到测试服务器。应用程序启动后,请切换到 J2EE 透视图,并在 Other Projects 下的 PackageStatusModule 项目中找到名为 PackageStatusExport_PackageTrackingServiceHttp_Service.wsdl 的文件。此文件是作为创建 Web 服务绑定(用于中介模块导出)的一部分生成的。右键单击该文件,并选择 Web services => Test with Web Services Explorer。
使用跟踪号 123 测试 ESB 服务调用。结果应该与以前的相同,只是这次您会在服务器控制台中看到更多的打印输出,因为正在调用 Logger 元素。在缺省情况下,该元素将消息记录在 Cloudscape® 数据库中。我们稍后将对它进行检查,以了解记录了哪些条目。
但是,请首先打开测试服务器的管理控制台,方法是在 Servers 视图中右键单击它,并选择 Run administrative console。在管理控制台中,导航到 SCA Modules 页,如图 9 所示。
图. SCA Modules 页
单击 PackageStatusModule 模块链接。在出现的页面上,单击 Additional Properties 下的 Module Properties,并在接下来的页面上,请注意我们前面提升的两个属性的显示方式及其值:
图 10. 模块属性
将 RequestMessageLogger.root 属性更改为“/body”。单击 OK 并保存更改。从管理控制台窗口注销,并将其关闭。
现在,运行前面在 Web Services Explorer 中运行的同一测试。但这次使用“456”作为跟踪号。这将帮助您区分记录的消息。
运行测试后,请停止服务器,以便解除 Logger 数据库上的锁,从而使您能够检查记录的消息。使用位于 [WebSphere Integration Developer 安装目录]\runtimes\bi_v6\cloudscape\bin\embedded 目录中的 cview 实用工具。启动该实用工具,选择 File => Open 菜单选项,并找到位于 [WebSphere Integration Developer 安装目录]\pf\esb\databases 目录中的 EsbLogMedDB 数据库。打开 MSGLOG 表,并使用 Data 选项卡检查其内容。窗口应类似于图 11。
图 11. cview 实用工具
上面您部署了两个实际的服务提供程序实例,一个是主要的 PackageStatusService,另一个是名为 PackageStatusBackupService 的附加服务。在许多情况下,您希望能够方便地切换被调用的服务端点;其中一种情况是从开发环境转移到测试环境。那么,如何在不更改 WebSphere Integration Developer 中的模块的情况下将消息路由到备份服务,哪些需要重新部署?共有两种方法,这里我们将讨论其中的一个。
您可以将消息动态地路由到新的端点地址,方法是将附加元素(即 MessageElementSetter 元素)插入到流程。此元素可以更新上下文标头,从而导致消息流向不同的地址,而不是在导入的绑定中配置的地址。可以有选择地将其与注册中心(如 WebSphere Registry and Repository)的查找结合起来(为此,WebSphere ESB 和 WebSphere Integration Developer 的版本 6.0.2 中提供了附加的新元素)。此方法的详细信息超出了本文讨论的范围,但是您可以在“ WebSphere Enterprise Service Bus V6.0.2 中的动态路由改进”一文中找到详细的信息和场景。
您可以在服务器的管理控制台中更改 SCA 模块的端点地址。如果您停止服务器,重新启动它,然后运行管理控制台,并打开 SCA Modules 页,则和前面的完全一样。选择 PackageStatusModule 模块,并展开 Module components 下的 Imports 节点(图 12)。
图 12. 模块组件
单击 Binding 链接,打开一个页面,该页面允许您覆盖此导入使用的端点 URL。将其更改为备份服务的端点 URL,即 http://localhost:9082/PackageStatusServiceBackup/services/PackageTrackingService。和前面一样,我们假设您的测试服务器使用的端口为 9082。如果不是这样,还需要更新 URL,以使用正确的端口。
最后,单击 OK 并保存更改。完成之后,再次运行测试,您将在服务器控制台中看到备份服务的打印输出。
在本文中,您开始使用 Web 服务 (SOAP/HTTP) 将您的服务与 WebSphere ESB 进行交互。在不同的端点地址下,您部署了两个相同的 Web 服务,二者同时返回包的状态信息。在服务请求程序和服务提供程序之间建立的中介流组件非常直观,并简单地记录了通过数据库的所有消息。
然后,学习了 WebSphere ESB V6.0.2 中对提升属性的支持如何使您能够在运行时通过管理控制台更改中介元素的属性。在本示例中,您更改了记录的消息的详细内容的级别。
最后向您介绍了如何使用管理控制台来更改具有 Web 服务绑定的导入所使用的端点地址,这允许您将请求从一个服务提供程序重新路由到另一个服务提供程序——同样不需要将模块重新加载到开发工具并重新部署它。
| 描述 | 名字 | 大小 | 下载方法 |
|---|---|---|---|
| Code sample | part3-downloads.zip | 52 KB | FTP |
- 您可以参阅本文在 developerWorks 全球站点上的 英文原文 。
- IBM 企业服务总线介绍
- WebSphere Enterprise Service Bus 产品页
- WebSphere Enterprise Service Bus 与 WebSphere Integration Developer 入门
- 为 WebSphere Enterprise Service Bus 开发自定义中介
- 使用 JMS 和 WebSphere ESB 构建强大而可靠的 SOA
- WebSphere Enterprise Service Bus V6.0.2
- 教程:使用 Java Message Service (JMS) 客户机调用 Web 服务
- 服务组件体系结构
- 红皮书:Enabling SOA Using WebSphere Messaging

