处理 BLOB 域的消息

本主题提供特定于处理属于 BLOB 域、由 BLOB 解析器解析的消息的信息。

您无法使用 BLOB 消息的内容,因为它没有预定义的结构。但您可以根据它在位流中的已知位置查阅其内容,并在对其内容了解最少的情况下处理该消息。

BLOB 消息体解析器与其他消息体解析器创建树结构的方式不同。它有一个根元素 BLOB。该根元素有一个包含数据的子元素,也称为 BLOB。

如果知道 BLOB 数据内特殊信息段的位置,可以使用子串来查阅消息内容。例如,以下表达式标识了消息体的第十个字节:

InputBody.BLOB.BLOB[10]

以下表达式引用了从偏移量 10 开始的 10 个字节消息数据:

SUBSTRING(InputBody.BLOB.BLOB from 10 for 10)

BLOB 消息使用示例

本示例显示了如何使用可变长度 BLOB 消息。该示例假设您已经配置了接收可变长度 BLOB 消息的消息流,通过调用 MRM 解析器解析其中一些字段,并根据已解析的信息将输出消息路由到正确的输出队列。

输入消息的格式为 BLOB,并假设为包含嵌入的 NULL(“x00”),因此它不能被定义为以 null 结束。

本示例显示完成下列操作所需的 ESQL:

  • 计算 BLOB 消息长度
  • 将它转换为十六进制格式
  • 将它添加到 BLOB 消息的开始处

通过这样做,您可以用后跟 BLOB 消息的整数长度字段定义消息模型。

本示例还显示如何将 BLOB 消息转换为 CWF、处理消息和剥除添加的长度字段。

在本示例中,输入记录具有如下格式:

  • 版本号:字符串,11 个字符
  • 存储号:字符串,10 个字符

    此字段根据客户定义的条件将消息路由到不同队列的整数。

  • 存储数据:可变长度二进制数据

定义新消息

定义包含以下元素和类型的新消息 BLOB_Example:

  • B_LEN,xsd:integer
  • VERSION_NUM,xsd:string,Length 11
  • STORE_NUM,xsd:string,Length 10
  • BIN_BLOB,xsd:binary,Length Value B_LEN

创建消息流

此部分描述消息流的特性。如果您要实现此示例流,则必须完成消息流定义(例如,通过创建三个子流来替换此处使用的输出节点处理错误、未知和故障情况),并为其部署和执行提供任何必需的支持(例如,为流部署到的代理创建队列管理器上的入站和任何出站队列)。

  1. 创建子流 LESS_THAN。创建 LESS_THAN 子流中描述了该任务。
  2. 创建新消息流。 将以下节点添加到消息流编辑器视图:一个 MQInput 节点、一个 Compute 节点、一个 ResetContentDescriptor 节点、一个 Filter 节点、三个 MQOutput 节点和 LESS_THAN 子流。
  3. 将 MQInput 节点的名称更改为 INQUEUE,并将它的队列名称属性设置为 INQUEUE
  4. 将 output 终端连接到 Compute 节点。
  5. 将 Compute 节点的名称从它的缺省值更改为 Add_length。配置 Compute 节点以计算 BIN_BLOB 的长度,并将它添加到 B_LEN 字段中 BLOB_Example 消息的起始处:
    1. 右击该节点,然后单击打开 ESQL
    2. 为此节点在模块中编码以下 ESQL:
      -- Declare local variables
                    DECLARE I INTEGER 1;
                    DECLARE J INTEGER CARDINALITY(InputRoot.*[]);
      DECLARE MSGLEN CHARACTER; 
      DECLARE NUMBER INTEGER; 
      DECLARE RESULT INTEGER; 
      DECLARE REM    INTEGER; 
      -- Copy message headers
                               WHILE I < J DO
                                       SET OutputRoot.*[I] = InputRoot.*[I];
      SET I = I + 1;
      END WHILE;
      --
      -- Set MSGLEN to non NULL to avoid errors when concatenating the first time -- 
      SET MSGLEN = 'X'; 
      --
      -- Get the length of the BLOB and substract the length of VERSION_NUM and STORE_NUM (11+10) 
      SET NUMBER = LENGTH("InputRoot"."BLOB"."BLOB")-21; 
      --
      -- Convert NUMBER to hexadecimal. The remainder of dividing by 16 is calculated recursively. -- 
      WHILE NUMBER > 15 DO
         SET RESULT = NUMBER/16;      
         SET REM    = NUMBER - RESULT*16;      
      SET MSGLEN =           
      CASE
           WHEN REM < 10  THEN CAST(REM AS CHARACTER) || MSGLEN               
           WHEN REM = 10  THEN 'A' || MSGLEN              
           WHEN REM = 11  THEN 'B' || MSGLEN              
           WHEN REM = 12  THEN 'C' || MSGLEN              
           WHEN REM = 13  THEN 'D' || MSGLEN               
           WHEN REM = 14  THEN 'E' || MSGLEN              
           ELSE                'F' || MSGLEN          
      END;
         SET NUMBER = RESULT; 
      END WHILE;
      SET REM = NUMBER;     
      SET MSGLEN =           
      CASE
           WHEN REM < 10  THEN CAST(REM AS CHARACTER) || MSGLEN               
           WHEN REM = 10  THEN 'A' || MSGLEN              
           WHEN REM = 11  THEN 'B' || MSGLEN              
           WHEN REM = 12  THEN 'C' || MSGLEN              
           WHEN REM = 13  THEN 'D' || MSGLEN               
           WHEN REM = 14  THEN 'E' || MSGLEN              
           ELSE                'F' || MSGLEN          
      END;
      --
      -- Add leading '0's up to a length of 9 to be able to cast as BLOB. 
      -- Remember it started with MSGLEN set to X (length 1) 
      WHILE LENGTH(MSGLEN) < 9 DO       
         SET MSGLEN = '0' || MSGLEN; END WHILE; 
      --
      -- Change to appropriate endian (PLATFORM DEPENDENT)
      -- If no endian swapping needed then remember to get rid of the last character as below -- 
      SET MSGLEN = SUBSTRING(MSGLEN FROM 1 FOR 8);
      --
      SET MSGLEN = SUBSTRING(MSGLEN FROM 7 FOR 2) || SUBSTRING(MSGLEN FROM 5 FOR 2) ||
                   SUBSTRING(MSGLEN FROM 3 FOR 2) || SUBSTRING(MSGLEN FROM 1 FOR 2);
      SET "OutputRoot"."BLOB"."BLOB" = CAST(MSGLEN AS BLOB) || "InputRoot"."BLOB"."BLOB";
  6. 将 Compute 节点的 out 终端连接到 ResetContentDescriptor 节点。
  7. 将 ResetContentDescriptor 节点名更改为 ResetContent_2_MRM。按如下所示配置节点:
    1. 消息域设置为 MRM
    2. 选中重置消息域复选框。
    3. 消息集设置为消息集的标识,从中您定义 BLOB_Example 消息。
    4. 选中重置消息集复选框。
    5. 消息类型设置为 BLOB_Example
    6. 选中重置消息类型复选框。
    7. 设置为您已经定义的 CWF 格式的名称(例如缺省值 CWF1)。
    8. 选中重置消息格式复选框。
  8. 将 ResetContentDescriptor 节点的 out 终端连接到 Filter 节点。
  9. 将 Filter 节点的名称更改为 Route_2_QUEUE。按如下所示配置节点:
    1. 右击该节点,然后单击打开 ESQL
    2. 在此节点的 ESQL 模块中,为以下 ESQL 语句进行编码:
      CAST("Body"."e_STORE_NUM" AS INTEGER) < 151

      该语句基于随机的假设,进入消息的存储号小于 151,且消息被路由到特定的队列。您可以为任何其他合适的测试进行编码。

  10. 如下所示,连接 Filter 输出终端:
    1. True 终端连接到名为 LESS_THAN 的子流节点(请见下方)。
    2. False 终端连接到名为 GREATER_THAN 的 MQOutput 节点,将该节点的队列名属性设置为 GREATER_THAN
    3. Unknown 终端连接到名为 INVALID 的 MQOutput 节点,将该节点的队列名属性设置为 INVALID
    4. Failure 终端连接到名为 ERROR 的 MQOutput 节点,将该节点的队列名属性设置为 ERROR

创建 LESS_THAN 子流

该子流处理具有预期格式的消息(Filter 节点中执行的测试返回真)。成功消息将按其原始格式写至输出队列;消息从 MRM 转换回 BLOB,并除去添加的四个字节(B_LEN 字段)。

针对这个子流执行以下操作:

  1. 创建名为 LESS_THAN 的新消息流。
  2. 在“编辑器”视图中,添加一个 Input 节点、一个 ResetContentDescriptor 节点、一个 Compute 节点和一个 MQOutput 节点。
  3. 将 Input 节点的名称更改为 InputTerminal1 并将其 out 终端连接到 ResetContentDescriptor 节点。
  4. 将 ResetContentDescriptor 的名称更改为 ResetContent_2_BLOB 并配置该节点:
    1. 消息域设置为 BLOB
    2. 选中重置消息域复选框。
  5. 将 ResetContentDescriptor 节点 out 终端连接到 Compute 节点。
  6. 将 Compute 节点的名称更改为 Remove_length,并配置该节点:
    1. 右击该节点,然后单击打开 ESQL
    2. 为此节点在模块中编码以下 ESQL:
      -- Copy message headers
                    DECLARE I INTEGER 1;
                    DECLARE J INTEGER CARDINALITY(InputRoot.*[]);
                               WHILE I < J DO
                                       SET OutputRoot.*[I] = InputRoot.*[I];
      SET I = I + 1;
      END WHILE;
      --
      -- Remove the 4 bytes length field added previously -- 
      SET "OutputRoot"."BLOB"."BLOB" = SUBSTRING("InputRoot"."BLOB"."BLOB" FROM 5);

      这个 Compute 节点除去添加到 BLOB 消息开头处的四个字节,以支持它的处理。

      请注意变量 J 的使用,它初始化到消息中现有头的基数值。这比计算循环的每个迭代的基数更有效,如果您编写以下 WHILE 语句则会进行这种计算:

      WHILE I < CARDINALITY(InputRoot.*[]) DO
  7. 将 Compute 节点的 out 终端连接到 MQOutput 节点。
  8. 将 MQOutput 节点的名称更改为 Output_success,并配置节点,设置队列管理器名称队列名称。您会发现提升这些 MQOutput 节点属性是有用的,这样您便可以在消息流级别指定这些属性。
声明 | 商标 | 下载 | | 支持 | 反馈
Copyright IBM Corporation 1999, 2006 最后更新:2006/05/19
ac11640_