使用《Oracle Service Bus 11g Development Cookbook》中的方案迅速推出一批全新的面向服务和消息的解决方案
2012 年 3 月
(单击图像了解更多信息。) |
本文介绍从《Oracle Service Bus 11g Development Cookbook》(Packt 2012) 一书中包含的 80 个方案中专门选出的 3 个方案,集中展示如何在 Oracle Service Bus 11g 上高效开发面向服务和消息的(集成)解决方案。这里介绍的这
3 个方案主要完成以下任务:
- 使用 JMS 传输来传递消息:向 JMS 队列/主题发送消息(第 3 章)
- 使用文件和电子邮件传输:使用文件传输写入文件(第 6 章)
- 通信、流控制和消息处理:使用自定义 XPath 函数。(第 9 章)
组件
为开发和测试这些方案,需要在系统上安装 Oracle Service Bus 11g (OSB) 补丁集 3(11.1.1.4 或更高版本)以及 Oracle
Database 11g(XE 或企业版)。
为使用基于 Web 的控制台,必须有 Internet Explorer 或 Firefox。
所有方案都是在 Oracle Service Bus 11g 和 Oracle SOA Suite 11g 的所谓“开发人员”安装上开发的。这意味着所有软件运行在单个管理服务器上,不需要其他托管服务器。在开始撰写该书之时,Oracle Service Bus 补丁集 3 (11.1.1.4) 是当时最新版本,我们使用此版本实现了所有方案。在解读屏幕截图时请记住这一点(尽管大多数情况下这是显然的)。但当输入 OSB 服务器的 URI(例如打开 Service Bus 控制台)时,这些差异还是有关系的。在我们的安装中,只有一个管理服务器,这些方案中所使用的端口始终是
7001。如果安装不同,请确保进行相应更改。
为指导您完成各种组件的安装,我们编写了一个额外的文档 OsbCookbookInstallationGuide.pdf,该文档包含在此 zip 文件中:osb-cookbook-1540083.zip。
本文所含方案的环境由构件集组成,包括要在 Oracle WebLogic Server 上配置的 JMS 队列和连接工厂。这些构件通过从 ANT 脚本调用的一个 WLST 脚本进行安装。该脚本也包含在上述 zip 文件 (osb-cookbook-1540083.zip)
中。解压缩之后,可以通过运行setup\wlst\install.cmd 安装该文件。
方案 1:向 JMS 队列/主题发送消息
在这个方案中,我们将创建一个业务服务,它向 JMS 队列或 JMS 主题发送一条消息。因为从业务服务的角度来看,写入队列和主题非常类似,所以我们决定将其合并成一个方案。我们将使用和配置 Oracle Service Bus 提供的 JMS 传输。
准备
对于此方案,我们将使用 OSB Cookbook 标准环境中的 DestinationQueue 或 DestinationTopic,实现一个向队列/主题发送消息的业务服务。我们不在此方案中实现代理服务。而是直接在 OSB 控制台上测试该业务服务。
具体步骤
首先我们来创建向 DestinationQueue 发送消息的 JMSProducer 业务服务。在更多内容 一节,我们将介绍为向 JMS 主题发送消息而需要进行的改动。在 Eclipse OEPE 中,执行以下步骤:
- 创建一个新的 OSB 项目 writing-to-a-jms-queue 并在其中创建一个 business 文件夹。
- 创建一个新的业务服务并将其命名为 JMSProducer。
- 导航至 General 选项卡。
- 将 Service Type 选项设置为 Messaging Service。
- 导航至 Messaging 选项卡。
- 将 Request Message Type 选项设置为 Text。
- 将 Response Message Type 设置为 None。
- 导航至 Transport 选项卡。
- 选择 jms 作为 Protocol 下拉列表框的值。
- 在 EndpointURI 域中输入 jms://localhost:7001/weblogic.jms.XAConnectionFactory/jms.DestinationQueue,单击 Add。
- 导航至 JMS Transport 选项卡。
- 将 Destination Type 选项设置为 Queue。
- 将 Message Type 选项设置为 Text。
- 将 Response Queues 选项设置为 None。
- 将项目部署到 OSB 服务器。
向队列发送消息所需的就是这些了。
现在我们来测试该业务服务。在 OSB 控制台中,执行以下步骤: - 在左侧 Project Explorer 树中单击 Projects | writing-to-jms-queue | business 导航至 JMSProducer 业务服务。
- 单击 Actions 单元格中的 Launch Test Console 图标(臭虫图标)。
- 在 Payload 域中输入要发送的消息文本。
- 单击 Execute。
- 随即调用业务服务,将在 Response Document 中显示 There was no response 消息。这是因为,前面我们通过选择 Messaging Service 并将 Response Message Type 设置为 None 配置了单向消息交换模式。如果从代理服务调用该业务服务,也不会得到响应。
下面通过在 WebLogic Console 中执行以下步骤检查 DestinationQueue 中是否存在该消息: - 在左侧的 Domain Structure 树中,导航至 Services | Messaging | JMS Modules。
- 单击 OsbCookbookResources。
- 单击 DestinationQueue。
- 导航至 Monitoring 选项卡。
- 选中 OSBBookJMSModule!DestinationQueue 前面的复选框。
- 单击 Show Messages。
- 单击(消息 ID)ID:<nnnnn.nnnnnnnn.n>
- 随即显示消息详细信息,包括消息内容和 JMS 属性。
工作原理
只需使用 JMS 传输配置业务服务,就可以将消息从 OSB 发送到 JMS 队列或主题。该队列或主题可能驻留于:
- 与 OSB 服务器相同的 WebLogic 实例
- 远程 WebLogic 实例
- 任何符合 JMS 的 JMS 服务器。
这里我们只是配置了业务服务并通过 OSB 控制台对其进行了测试。在实际情况中,我们是从代理服务通过 Routing 或 Publish 操作来调用业务服务的。如果无需转换消息,简单的直接传递代理服务就够了。
更多内容……
本节将讨论 JMS Transport 选项卡上的一些高级设置,以及为发送到 JMS 主题(而不是 JMS 队列)而需对方案进行的更改。
JMS Transport 上的高级设置
在业务服务配置的 JMS Transport 选项卡上可以设置一些高级设置,如下图所示。
Enable Message Persistence 选项默认为启用状态,这可以保证消息传递,因为消息是持久保存的,可以平安渡过服务器关闭和故障期。要提高吞吐量,请取消选中此选项(假定偶尔丢失消息是可以容忍的)。
在 Expiration 域中以毫秒为单位设置时间间隔,以指定消息的生存周期。生存周期过后,消息将根据 JMS 目标(即队列)上定义的Expiration Policy 自动处理、丢弃、记录或重定向到另一个 JMS 目标。
Expiration 的默认值 0 意味着消息永不过期,因此永久等待使用或直至服务器关闭(如果消息不是持久保存的)。
任何 JMS 目标都可以在其配置过程中通过 WebLogic Console 进行 Time-to-Live Override 设置,从而覆盖业务服务上设置的 Expiration。
发送到 JMS 主题
具体步骤 一节中给出的步骤同样也适用于发送到 JMS 主题。要从队列更改为 JMS 主题 DestinationTopic,请确保在第 10 步中在EndpointURI 中输入 jms://localhost:7001/weblogic.jms.XAConnectionFactory/jms.DestinationTopic,并在第
12 步中将Destination Type 选项设置为 Topic。将项目重新部署到 OSB 服务器。
这样,业务服务现在将写入 JMS 主题。对此我们可以通过 OSB 控制台执行以下步骤进行测试:
- 在左侧 Project Explorer 树中单击 Projects | writing-to-jms-topic | business 导航至 JMSProducer 业务服务。
- 单击 Actions 单元格中的 Launch Test Console 图标(臭虫图标)。
- 在 Payload 域中输入 This is a text message!。
- 单击 Execute。
- 随即执行业务服务,将在 Response Document 中显示 There was no response 消息。这是因为我们通过选择 Messaging Service 并只选择 Response Message Type 配置了单向消息交换模式。
下面通过在 WebLogic Console 中执行以下步骤检查 DestinationTopic 中是否存在该消息:
- 在左侧的 Domain Structure 树中,导航至 Services | Messaging | JMS Modules。
- 单击 OsbCookbookResources。
- 单击 DestinationTopic。
- 导航至 Monitoring 选项卡。
因为该主题没有任何订阅者,所以不持久保存消息。因此我们来向该主题添加订阅者:
- 导航至 Durable Subscribers 选项卡。
- 单击 New。
- 在 Subscription Name 域中输入 TopicSubscriber。
- 在 Client ID 域中输入 TopicSubscriber。
- 单击 OK。
重新测试业务服务,刷新 Durable Subscribers 选项卡。
- 选中 TopicSubscriber 前面的复选框。
- 单击 Show Messages。
- 单击(消息 ID)ID:<nnnnn.nnnnnnnn.n>。
- 随即显示消息详细信息,包括消息内容和 JMS 属性。
方案 2:使用文件传输写入文件
在这个方案中,我们将向本地文件系统(OSB 服务器本地)写入一个文件。我们将实现一个业务服务,该业务服务使用文件传输来完成此任务。此外,我们还将创建一个代理服务并通过使用 Transport Header 操作控制被写入文件的文件名。
具体步骤
首先我们实现一个将文件写入本地文件夹的业务服务。在 Eclipse OEPE 中执行以下步骤:
- 创建一个新的 OSB 项目并将其命名为 using-file-transport-to-write-to-file。
- 在该新项目中创建一个 business 文件夹。
- 在 business 文件夹中创建一个名为 WriteToLocalFile 的新业务服务。
- 在 General 选项卡中选择 Messaging Service 作为 Service Type 选项。
- 导航至 Messaging 选项卡并选择 Text 作为 Request Message Type。
- 保留 Response Message Type 设置为 None。
- 导航至 Transport 选项卡并从 Protocol 下拉列表中选择 file。
- 在 Endpoint URI 域中输入 file:///C:/work/destination 并单击 Add。
- 导航至 File Transport 选项卡。
- 在 Prefix 域中输入 Hello 并在 Suffix 域中输入 .txt。
- 将项目部署到 OSB 服务器。
写入文件的业务服务现已配置完毕,我们可以通过 Test Console 对它进行测试。在 Service Bus Console 中执行以下步骤:
- 单击左侧菜单中的 Project Explorer 并导航至 WriteToLocalFile 业务服务。
- 单击 Launch Test Console 图标。
- 在 Payload 域中输入 Hello world! 作为写入本地文件的内容。
- 单击 Execute。
- 测试结果显示如下图所示。没有响应,因为写入文件始终是单向操作。但元数据的内容将返回文件路径,即使用前缀 Hello 和后缀 .txt生成的名称。
- 检查是否已在指定位置创建文件。
现在我们有了一个可用于写入本地文件的业务服务。文件名已经生成。我们只能通过文件传输的配置来控制所使用的前缀和后缀。
要指定完整的文件名,可以在调用该业务服务的代理服务的 Routing 操作中使用 Transport Header 操作。
工作原理
只需使用一个配置了文件传输的业务服务,就可以将文件写入本地文件夹。在文件传输上配置的 Endpoint URI 定义了目标本地文件夹所在位置。如果该文件夹尚未存在,则由文件传输在写第一个文件时创建。
文件传输允许通过前缀和后缀选项对文件名进行一定程度的控制。但默认情况下,文件名的中间部分将基于一个类似 UUID 的字符串来生成。这样就可以保证文件名始终是唯一的。如果这不是我们所希望的行为,则可以使用 Transport Header 操作来覆盖文件名,如下一节在运行时指定文件名 所示。
如果文件已经存在,则文件名将附加“_N”,其中 N 是一个从 0 开始的数字。该字符串将添加到后缀前面,因此如果 targetFile.xml 已经存在于目标文件夹中,原始文件名 targetFile.txt 将扩展为 targetFile_0.txt。
更多内容……
在本节中,我们将讨论如何在运行时动态指定文件名以及如何使用 FTP 传输通过 FTP 将文件写入远程文件夹。
在运行时指定文件名
如果要覆盖由文件传输生成的文件名,则需在从代理服务调用业务服务时使用 Transport Header 操作设置一些传输头。
因此我们来创建一个代理服务,让其调用前面创建的业务服务。为简单起见,我们只使用生成服务功能基于现有业务服务创建一个代理服务并将协议更改为 Http 传输。在 Eclipse OEPE 中执行以下步骤:
- 创建 proxy 文件夹。
- 右键单击业务服务 WriteToLocalFile 并选择 Oracle Service Bus | Generate Proxy Service。
- 选择 Enter or select the parent folder 树中的 proxy 文件夹,在 File name 域中输入 WriteToLocalFile,单击 Finish。
- 导航至 Transport 选项卡并将 Protocol 更改为 http。
- 导航至 Message Flow 选项卡。
- 在生成的 Routing 节点的 Request Action 中插入 Transport Header 操作。
- 在 Transport Header 操作的 Properties 选项卡中,单击 Add Header。
- 选择 Defined 选项并在相应的下拉列表中选择 file 和 fileName。
- 选择 Set Header to 选项并单击 <Expression>。
- 在 Expression 域中输入 'TargetFile'(包括引号)。
- 将项目部署到 OSB 服务器。
现在可以通过 Test Console 测试代理服务。在 Service Bus Console 中执行以下步骤:
- 单击左侧菜单中的 Project Explorer 并导航至 proxy 文件夹中的 WriteToLocalFile 代理服务。
- 单击 Launch Test Console 图标。
- 在 Payload 域中输入 Hello world! 作为写入本地文件的内容。
- 单击 Execute。
- 测试结果应类似于下图所示。outbound 变量将显示用于写入文件的完整 filePath 值。该文件名使用来自文件传输配置的前缀 Hello 和后缀 .txt 以及来自 Transport Header 操作的名称 TargetFile 创建。
- 检查是否已在指定位置创建文件。
通过 FTP 将文件写入远程文件夹
我们可以使用 FTP 传输替换文件传输以通过 FTP 写入远程文件系统。
要将文件写入 FTP 服务器,在 Eclipse OEPE 中执行以下步骤:
- 创建一个名为 FTPUser.sa 的 Service Account 构件。
- 在 business 文件夹中创建一个新的业务服务 WriteToFtpFile。
- 在 General 选项卡中选择 Messaging Service 作为 Service Type 选项。
- 导航至 Messaging 选项卡并选择 Text 作为 Request Message Type。
- 保留 Response Message Type 为 None。
- 导航至 Transport 选项卡并从 Protocol 下拉列表中选择 ftp。
- 在 Endpoint URI 域中输入 ftp://localhost/ 并单击 Add。
- 导航至 FTP Transport 选项卡。
- 针对 User Authentication 选项选择 external user,然后单击 Browse 并选择 FTPUser Service Account 构件。
- 在 Prefix for destination File Name 域中输入 Hello,在 Suffix for destination File Name 域中输入 .txt。
- 针对 Transfer Mode 选项,选择 ascii。
现在可以从代理服务调用该业务服务,文件将写到 FTP 服务器。
方案 3:使用自定义 XPath 函数
在这个方案中,我们将演示如何实现自定义 XPath 函数以扩展 OSB 平台中可用的 XPath 函数集合。
准备
您可以将包含这个方案的基本配置的 OSB 项目从 \chapter-9\getting-ready\using-custom-xpath-function(包含在 osb-cookbook-1540083.zip 中)导入
Eclipse OEPE。
具体步骤
首先需要创建我们要作为自定义 XPath 函数公开的 Java 功能。我们将重用曾在“使用 Java Callout 操作调用 Java 代码”方案中使用的 Java 类,如下所示:
package osbcookbook.util.checksum; import java.util.zip.CRC32;
import java.util.zip.Checksum; public class ChecksumUtil {
public static long calculateChecksum(String data) {
Checksum checksum = new CRC32();
checksum.update(data.getBytes(), 0,
data.getBytes().length);
return checksum.getValue();
}
}
osb-cookbook-1540083.zip 中包含的 \chapter-9\getting-ready\misc\osb-checksum-util.jar 中提供了包含此类的 JAR。
接下来,需要在 OSB 服务器上配置 XPath 函数并将其映射到 ChecksumUtil 类的 calculateChecksum 方法。XPath 函数的配置保存在[WL_HOME]/Oracle_OSB1/config/xpath-functions 中。在资源管理器窗口中执行以下步骤。
- 导航至 [WL_HOME]/Oracle_OSB1/config/xpath-functions 文件夹。
复制 osb-built-in.xml 文件并将其粘贴为一个名为 osb-cookbook.xml 的新文件,此文件将容纳自定义 XPath 函数的定义。
- 在一个编辑器中打开 osb-cookbook.xml。
- 删除所有现有 <xpf:function> 元素并添加我们的函数,如下图所示:
- 保存此文件。
现在需要使该 JAR 对 OSB 服务器可用:
- 将 osb-checksum-util.jar 从 \chapter-9\getting-ready\misc 复制到 [WL_HOME]/Oracle_OSB1/config/xpath-functions 文件夹。
- 重新启动 Eclipse OEPE 和 OSB 服务器以重新加载配置。
现在来使用新的 XPath 函数。在 Eclipse OEPE 中执行以下步骤:
- 打开 Checksum 代理服务并导航至 Message Flow 选项卡。
- 将 Replace 操作插入 CalculateChecksumStage 中。
- 在 Replace 操作的 Properties 上,在 In Variable 域中输入 body。
- 单击 <Expression> 并选择 XQuery Functions 选项卡。
- 用 $body/text() 替换参数列表中的 $arg-string,单击 OK。
- 选择 Replace node contents option。
- 将项目部署到 OSB 服务器。
现在通过在 Service Bus Console 中执行以下步骤来测试代理服务:
- 在 Project Explorer 中导航至 using-custom-xpath-function 项目内的 proxy 文件夹。
- 单击 Checksum 代理服务的 Launch Test Console 图标。
- 在 Payload 域中输入 This is some text on which the Checksum will be calculated! 并单击 Execute。
- Response Document 部分的输出应显示与使用 Java Callout 操作的方案相同的校验和值 4265366956。
工作原理
我们已经看到了如何通过自定义 XPath 函数来扩展 OSB 平台上可用的 XPath 函数集。自定义 XPath 函数由一些 Java 代码来实现。为将 Java 功能映射到自定义 XPath 函数,需要将 Java 代码作为公共 Java 类中的公共静态方法公开。Java 方法不应产生副作用,例如,它不应更新任何数据库或参与全局事务。这种代码应通过 Java Callout 操作来调用。
只有在 OSB 可以找到 Java 类的情况下,自定义函数才会出现在 Eclipse OEPE 中。这种自定义 XPath 函数既可用于内联 XQuery 表达式(如 Replace 的情况所示),也可用于 XQuery 资源(正如 Oracle Service Bus 提供的任何其他函数一样)。
配置中的 isDeterministic 属性指定函数是确定性的还是非确定性的。确定性函数始终提供同样的结果,而非确定性函数则返回不同的结果。XQuery 标准建议函数应为确定性的,以便 XQuery 引擎能够执行优化。
更多内容……
自定义 XPath 函数也可以在 XQuery 资源中调用,如下图所示。
只需将 XPath 函数从 Expression Functions 树拖到 Expression 窗口中,就像对待任何其他内置 XPath 函数一样。
总结
本文所介绍的三个方案是作者专门从《Oracle Service Bus 11g Development Cookbook》一书中包含的 80 个方案中挑选出来的。我们希望您觉得这些方案有趣,并且希望能够激发您的更多兴趣。