接收一个 IBM® MQ 请求消息,将该消息传递给 IBM MQ ,然后将 IBM MQ 响应发送给发起请求的客户端。
准备工作
在此场景中, MQ 节点使用服务器绑定连接到 IBM MQ。 IBM MQ 因此必须安装在与集成节点相同的计算机上。 另外,您可以为 MQ 节点配置远程连接,但本场景中并未描述这些步骤。 如需更多信息,请参阅 “配置与 IBM MQ 的连接”。
关于此任务
“请求-响应”消息流是点到点应用程序的一种特殊形式。 有关这些应用程序的一般描述,请参阅 用于连接的节点。
此场景将用于连接客户机应用程序。
方案:
两个采用不同消息格式的应用程序通过在请求-响应消息处理方案中使用 IBM MQ 进行通信。 为了使应用程序能够成功通信,必须在 IBM App Connect Enterprise 中对请求和响应消息的消息格式进行转换。 在此场景中,后端应用程序由第三个消息流表示,用于演示消息的成功处理。
请求-响应模式需要两个消息流,因为 IBM MQ 是以异步方式处理消息的。 在 IBM App Connect Enterprise 中异步处理的消息不会等待响应,且 IBM MQ 也不会发送回复消息。 要处理应答,存储队列将获取原始消息的 ReplyToQ 属性,以便第二个消息流可以处理来自应用程序的应答。
此场景说明了如何创建请求和应答消息流,以及如何使用存储队列来存储消息状态信息。 表示后端应用程序的消息流修改消息中的“完成时间”值。
说明:
以下步骤将演示如何创建消息流和存储状态队列,以便处理来自 IBM MQ 的回复消息。
过程
- 使用以下节点创建名为 MQ_Task2_Request 的消息流,并在 描述 选项卡 节点名 属性中对其进行命名:
- 名为 Receive Message的 MQInput 节点。
- 四个名为 Transform Request Message, Save
MQMD Headers to LocalEnvironment, Set
New ReplyToQ和 Build State Message的 计算 节点。
- 两个名为 Output Request Message 和 Store
State Message的 MQOutput 节点。
有关更多信息,请参阅 创建消息流。
- 将 Receive Message MQInput 节点的 Out 终端连接到 Transform Request Message Compute 节点的 In 终端。
- 将 Transform Request
Message Compute 节点的 Out 终端连接到 Save MQMD Headers to LocalEnvironment Compute 节点的 In 终端。
注: 您可以为 Receive Message MQInput 节点与 Save
MQMD Headers to LocalEnvironment Compute 节点之间所需的消息处理添加自己的变换节点或子流。 在此场景中, Transform
Request Message Compute 节点是不变换消息的占位符。
- 将 Save MQMD Headers
to LocalEnvironment Compute 节点的 Out 终端连接到 Set New ReplyToQ Compute 节点的 In 终端。
- 将 Set New ReplyToQ Compute 节点的 Out 终端连接到 Output Request Message MQOutput 节点的 In 终端。
- 将 Output Request
Message MQOutput 节点的 Out 终端连接到 Build State Message Compute 节点的 In 终端。
- 将 Build State
Message Compute 节点的 Out 终端连接到 Store State Message MQOutput 节点的 In 终端。
现在,您必须为消息流的请求行为配置消息流节点。
- 设置 Receive
Message MQInput 节点的以下属性:
- 在 基本 选项卡上,将 队列名称 属性设置为 MQ.TASK2.IN1。
- 在 MQ 连接 选项卡上,将 连接 属性设置为 本地队列管理器,然后将 目标队列管理器 属性设置为 TASK2_QUEUE_MANAGER。
- 在 输入消息解析 选项卡上,将 消息域 属性设置为 XMLNSC。
- 设置 Transform
Request Message Compute 节点的以下属性:
- 将自动创建 ESQL 模块 MQ_Task2_Request_Transform_Reply_Message。 在 " 应用程序开发" 视图中,打开 ESQLs,然后打开 MQ_Task2_Request_Transform_Reply_Message 模块。
- 将下列 ESQL 复制到模块中:
CREATE COMPUTE MODULE MQ_Task2_Request_Transform_Reply_Message
CREATE FUNCTION Main() RETURNS BOOLEAN
BEGIN
SET OutputRoot = InputRoot;
RETURN TRUE;
END;
END MODULE;
Transform Request
Message 计算 不会变换消息,而是充当此场景的占位符。
- 设置 Save
MQMD Headers to LocalEnvironment Compute 节点的以下属性:
- 在 基本 选项卡上,将 计算方式 属性设置为 LocalEnvironment。
- 将自动创建 ESQL 模块 MQ_Task2_Request_Save_MQMD_Headers_to_LocalEnvironment。 在 " 应用程序开发" 视图中,打开 ESQLs,然后打开 MQ_Task2_Request_Save_MQMD_Headers_to_LocalEnvironment 模块。
- 将下列 ESQL 复制到模块中:
CREATE COMPUTE MODULE MQ_Task2_Request_Save_MQMD_Headers_to_LocalEnvironment
CREATE FUNCTION Main() RETURNS BOOLEAN
BEGIN
SET OutputLocalEnvironment.Variables.OriginalMQMD = InputRoot.MQMD;
RETURN TRUE;
END;
END MODULE;
Save
MQMD Headers to LocalEnvironment Compute 节点将原始消息的 MQMD 保存到本地环境变量中,然后由 Build
State Message Compute 节点稍后在消息流中检索该变量。
- 设置 Set New
ReplyToQ Compute 节点的以下属性:
- 将自动创建 ESQL 模块 MQ_Task2_Request_Set_New_ReplyToQ。 在 " 应用程序开发" 视图中,打开 ESQLs,然后打开 MQ_Task2_Request_Set_New_ReplyToQ 模块。
- 将下列 ESQL 复制到模块中:
CREATE COMPUTE MODULE MQ_Task2_Request_Set_New_ReplyToQ
CREATE FUNCTION Main() RETURNS BOOLEAN
BEGIN
SET OutputRoot = InputRoot;
SET OutputRoot.MQMD.ReplyToQ = 'MQ.TASK2.BACKEND.RESP1';
SET OutputRoot.MQMD.ReplyToQMgr = 'TASK2_QUEUE_MANAGER';
RETURN TRUE;
END;
END MODULE;
Set
New ReplyToQ Compute 节点为 ReplytoQ 设置新值,以便使用 Reply 消息流队列。
- 设置 Output Request
Message MQOutput 节点的以下属性:
- 在 基本 选项卡上,将 队列名称 属性设置为 MQ.TASK2.BACKEND.REQ1。
- 在 高级 选项卡上,选择 新建消息标识 属性。
- 设置 Build State
Message Compute 节点的以下属性:
- 将自动创建 ESQL 模块 MQ_Task2_Request_Build_State_Message。 在 " 应用程序开发" 视图中,打开 ESQLs,然后打开 MQ_Task2_Request_Build_State_Message 模块。
- 将下列 ESQL 复制到模块中:
CREATE COMPUTE MODULE MQ_Task2_Request_Build_State_Message
CREATE FUNCTION Main() RETURNS BOOLEAN
BEGIN
CALL CopyMessageHeaders();
SET OutputRoot.MQMD.CorrelId = InputLocalEnvironment.WrittenDestination.MQ.DestinationData.msgId;
SET OutputRoot.MQMD.ReplyToQ = InputLocalEnvironment.Variables.OriginalMQMD.ReplyToQ;
SET OutputRoot.MQMD.ReplyToQMgr = InputLocalEnvironment.Variables.OriginalMQMD.ReplyToQMgr;
SET OutputRoot.BLOB.BLOB = InputLocalEnvironment.Variables.OriginalMQMD.MsgId;
RETURN TRUE;
END;
CREATE PROCEDURE CopyMessageHeaders() BEGIN
DECLARE I INTEGER 1;
DECLARE J INTEGER;
SET J = CARDINALITY(InputRoot.*[]);
WHILE I < J DO
SET OutputRoot.*[I] = InputRoot.*[I];
SET I = I + 1;
END WHILE;
END;
END MODULE;
Build State Message Compute 节点:
- 抽取写入 MQ.TASK2.BACKEND.REQ1 的消息的消息标识。
- 从 LocalEnvironment 抽取原始 ReplyToQ 和 ReplyToQMgr 值,然后这些值保存在 State Message MQMD 中。
- 从 LocalEnvironment 抽取原始 MessageId 值,然后将此值保存在 State Message 主体中。
- 请使用 BLOB 解析器读取和写入 State Message 的主体,因为 MessageId 是二进制数据。
- 设置 Store State
Queue MQOutput 节点的以下属性:
- 在 基本 选项卡上,将 队列名称 属性设置为 MQ.TASK2.STATE1。
- 在 高级 选项卡上,选择 新建消息标识 属性。
现在,您必须创建应答消息流。
- 使用以下节点创建名为 MQ_Task2_Reply 的消息流,并在 描述 选项卡的 节点名 属性中对其进行命名:
- 名为 Receive Backend Application Reply的 MQInput 节点。
- 名为 Get Original MQMD的 MQGet 节点。
- 名为 Send Reply的 MQOutput 节点。
- 两个 计算 节点,名为 Transform Reply Message 和 Set
CorrelID And RTQ。
- 两个 Throw 节点,名为 Handle MQGet Warning 和 Handle
Error No Store Message。
- 将 Receive Backend
Application Reply MQInput 节点的 Out 终端连接到 Transform Reply Message Compute 节点的 In 终端。
- 将 Transform Reply
Message Compute 节点的 Out 终端连接到 Get Original MQMD MQGet 节点的 In 终端。
- 将 Get Original
MQMD MQGet 节点的 Warning 终端连接到 Handle MQGet Warning Throw 节点。
- 将 Get Original
MQMD MQGet 节点的 Failure 终端连接到 Handle Error Not Stored Message Throw 节点。
- 将 Get Original
MQMD MQGet 节点的 Out 终端连接到 Set CorrelID And RTQ Compute 节点。
- 将 Set CorrelID
And RTQ Compute 节点的 Out 终端连接到 Send Reply MQOutput 节点。
现在,您必须为消息流的回复行为配置消息流节点。
- 设置 Receive
Backend Application Reply MQInput 节点的以下属性:
- 在 基本 选项卡上,将 队列名称 属性设置为 MQ.TASK2.BACKEND.RESP1。
- 在 输入消息解析 选项卡上,将 消息域 属性设置为 XMLNSC。
- 设置 Transform
Reply Message Compute 节点的以下属性:
- 将自动创建 ESQL 模块 MQ_Task2_Reply_Transform_Reply_Message。 在 " 应用程序开发" 视图中,打开 ESQLs,然后打开 MQ_Task2_Reply_Transform_Reply_Message 模块。
- 将下列 ESQL 复制到模块中:
CREATE COMPUTE MODULE MQ_Task2_Reply_Transform_Reply_Message
CREATE FUNCTION Main() RETURNS BOOLEAN
BEGIN
SET OutputRoot = InputRoot;
RETURN TRUE;
END;
END MODULE;
计算 不会变换消息。 Compute 节点是此场景中解法变换的占位符。
- 设置 Get Original
MQMD MQGet 节点的以下属性:
- 在 基本 选项卡上,将 队列名称 属性设置为 MQ.TASK2.STATE1。
- 在 MQ 连接 选项卡上,将 连接 属性设置为 本地队列管理器,然后将 目标队列管理器 属性设置为 TASK2_QUEUE_MANAGER。
- 在 输入消息解析 选项卡上,将 消息域 属性设置为 BLOB。
- 在 高级 选项卡上:
- 将复制消息属性设置为复制整个消息。
- 将复制 LocalEnvironment 属性设置为复制整个 LocalEnvironment。
- 在 请求 选项卡上:
- 将输入 MQMD 位置属性设置为 InputRoot.MQMD。
- 选择通过相关标识获取属性。
- 在 结果 选项卡上:
- 将输出数据位置属性设置为 OutputLocalEnvironment.ResultRoot。
- 将结果数据位置设置为 ResultRoot。
- 设置 Set CorrelId
And RTQ Compute 节点的以下属性:
- 在 基本 选项卡上,将 计算方式 属性设置为 MQ.TASK2.STATE1。
- 将自动创建 ESQL 模块 MQ_Task2_Reply_Set_CorrelId_And_RTQ。 在 " 应用程序开发" 视图中,打开 ESQLs,然后打开 MQ_Task2_Reply_Set_CorrelId_And_RTQ 模块。
- 将下列 ESQL 复制到模块中:
CREATE COMPUTE MODULE MQ_Task2_Reply_Set_CorrelId_And_RTQ
CREATE FUNCTION Main() RETURNS BOOLEAN
BEGIN
SET OutputRoot = InputRoot;
SET OutputRoot.MQMD.CorrelId = InputLocalEnvironment.Variables.ResultRoot.BLOB.BLOB;
SET OutputLocalEnvironment.Destination.MQ.DestinationData[1].queueName = InputLocalEnvironment.Variables.ResultRoot.MQMD.ReplyToQ;
SET OutputLocalEnvironment.Destination.MQ.DestinationData[1].queueManagername = InputLocalEnvironment.Variables.REResultRoot.MQMD.ReplyToQMgr;
RETURN TRUE;
END;
END MODULE;
Set CorrelId And
RTQ Compute 节点:
- 从 State Message MQMD 抽取 ReplyToQ 和 ReplyToQMgr。
- 设置 CorrelId 以作为原始 State Message 主体中的 MessageId 值。 CorrelId 用于应答消息流。
- 设置 Send Reply MQOutput 节点的以下属性:
- 在 高级 选项卡上,将 目标方式 属性设置为 目标列表
通过在 "目标列表" 方式下设置 MQOutput 节点,可以动态设置输出队列。
- 设置 Handle MQGet
Warning Throw 节点的以下属性:
- 在 基本 选项卡上,在 消息文本 字段中输入错误消息文本。
例如, "MQGet 返回了警告。"
如果在来自 MQGet 节点的消息中出现警告,那么 Handle_MQGet_Warning Throw 节点将返回有关此警告的错误消息。 消息树包含 MQMD 和接收到的任何消息内容。
- 设置 Handle Error
Not Stored Message Throw 节点的以下属性:
- 在 基本 选项卡上,在 消息文本 字段中输入错误消息文本。
例如, "MQGet 错误,未接收到商店消息队列。"
如果由于 MQGet 节点无法从商店队列获取消息而发生错误,那么 Handle_Error_Not_Stored_Message 计算 节点将返回错误消息。 消息未进行处理。
您无法将来自应答消息流的消息返回到请求消息流。 因此,您必须考虑在消息传递体系结构中比消息流节点提供的错误处理选项更高的级别进行错误处理。
消息流现在可以与后端应用程序进行通信。 对于此场景,创建第三个消息流以表示此应用程序。
缺省情况下,后端应用程序将消息的 MessageId 复制到其 CorrelId,并且此值随后将在应答消息中进行发送。 但是,由于在此场景中未使用实际应用程序,因此 Save
MQMD Headers to LocalEnvironment Compute 节点在步骤 10 中对请求消息流执行了此操作。
为了演示在 "应答" 消息流中成功处理后端应用程序,
Compute 节点会修改消息中的 "完成时间" 值。
- 使用以下节点创建名为 MQ_Task2_BackendApp 的消息流,并在 描述 选项卡的 节点名 属性中对其进行命名:
- 名为 Get Request Message的 MQInput 节点。
- 名为 Modify Completion Time的 Compute 节点。
- 名为 Put Reply Message的 MQReply 节点。
- 将 Get Request
Message MQInput 节点的 Out 终端连接到 Modify Completion Time Compute 节点的 In 终端。
- 将 Modify Completion
Time Compute 节点的 Out 终端连接到 Put Reply Message MQReply 节点的 In 终端。
- 设置 Get Request
Message MQInput 节点的以下属性:
- 在 基本 选项卡上,将 队列名称 属性设置为 MQ.TASK2.BACKEND.REQ1。
- 在 MQ 连接 选项卡上,将 连接 属性设置为 本地队列管理器,然后将 目标队列管理器 属性设置为 TASK2_QUEUE_MANAGER。
- 在 输入消息解析 选项卡上,将 消息域 属性设置为 XMLNSC。
- 设置 Modify Completion
Time Compute 节点的以下属性:
- 将自动创建 ESQL 模块 MQ_Task2_BackendApp_Modify_Completion_Time。 在 " 应用程序开发" 视图中,打开 ESQLs,然后打开 MQ_Task2_BackendApp_Modify_Completion_Time 模块。
- 将下列 ESQL 复制到模块中:
CREATE COMPUTE MODULE MQ_Task2_BackendApp_Modify_Completion_Time
CREATE FUNCTION Main() RETURNS BOOLEAN
BEGIN
SET OutputRoot = InputRoot;
SET OutputRoot.XMLNSC.SaleEnvelope.TimeStamp = CURRENT_GMTTIMESTAMP;
RETURN TRUE;
END;
END MODULE;
Modify Completion
Time Compute 节点表示此场景中的解决方案变换。 Compute 节点向消息添加时间戳记值,该值显示处理时间。
- 设置 Get Request
Message MQReply 节点的以下属性:
- 在 基本 选项卡上,将 队列名称 属性设置为 MQ.TASK2.BACKEND.REQ1。
- 在 MQ 连接 选项卡上,将 连接 属性设置为 本地队列管理器,然后将 目标队列管理器 属性设置为 TASK2_QUEUE_MANAGER。
- 保存消息流。
结果
- 请求消息流运行时,将进行以下操作:
- MQInput 节点读取一个 IBM MQ 请求消息。
- 原始消息转换为后端应用程序的等效格式。
- 为应答消息流的输入消息设置 ReplyToQ 和 ReplyToQMgr 详细信息。
- 系统会创建一个 IBM MQ 消息,其中包含经过转换的消息。 此消息发送到后端消息流。
- 原始的MessageId、 ReplyToQ 和 ReplyToQMgr 详细信息将保存在一个单独的 IBM MQ 消息中,以便后续由Reply消息流进行检索。
应答消息流运行时,将进行以下操作:
- MQInput 从后端应用程序读取包含数据格式消息的 IBM MQ 消息。
- 消息转换为请求者应用程序的等效格式。
- MQGet 节点通过读取用于在请求消息流中存储这些信息的 IBM MQ 消息,获取原始请求消息的CorrelId、 ReplyToQ 和 ReplyToQMgr 详细信息。
- 系统将生成一条 IBM MQ 消息,其中包含经过转换的消息以及检索到的CorrelId、 ReplyToQ 和 ReplyToQMgr 值。