您现在的位置: 教育资源库 >> 电脑学院 >> 认证考试 >> IBM认证 >> 正文

WebSphere MQ Solution Designer 认证考试 996 准备: 第 5 部分,其他 MQI 主题(下)_5151doc

WebSphere MQ Solution Designer 认证考试 996 准备: 第 5 部分,其他 MQI 主题(下)
作者:未知 文章来源:网络 点击数: 更新时间:2010-1-14

  MQI 安全性

  消息上下文

  消息上下文允许检索消息的应用程序,以了解有关消息的发起者信息。检索应用程序可以:

  检查发送应用程序的权限。

  使用发起者的信息执行一些计帐功能(即费用分摊)。

  保留已处理的消息的审核记录。

  发起用户和应用程序的信息包含在消息描述符的八个字段中。这些字段作为一个组称为上下文 字段。该信息进一步划分为两部分:标识数据和来源数据。

  这些字段的设置和使用应该受到谨慎的控制。

  上下文

  通常,应用程序将不会明确更新上下文字段。缺省行为是队列管理器设置所有字段。应用程序通常不会被授权更新上下文字段。

  在只是传递消息的应用程序情况下,可以将上下文信息从输入消息传递到输出消息(如果获得授权的话)。

  在某些情况下,只有上下文信息的标识数据部分才会被传递或更新。同样,应用程序和用户必须被授权执行这些操作。

  通常,业务应用程序本身不关心上下文字段;正如您将看到的,队列管理器将更新它们。

  缺省上下文

  当应用程序发出 MQPUT 时,如果还没有采取操作来更新上下文字段,缺省情况下,队列管理器将按如下方式更新其中每个字段:

字段描述
UserIdentifier(用户标识符)在其下运行放置应用程序的用户标识符
AccountingTokenCICS——工作单元标识符
IMS——PSB 名称 + IMS 恢复令牌
OS/400——一个字节长度 + 作业计帐代码
UNIX——用户编号
ApplIdentityData为空
PutApplTypeCICS、UNIX、32 位,等等
PutApplName放置消息的应用程序的名称
PutDate放置消息的日期 (YYYYMMDD)
PutTime放置消息的时间 (HHMMSSTH)
ApplOriginData为空

  务必注意 UserIdentifier 是 12 个字符。在某些环境中,用户 ID 可以更大(例如,Windows 中的 Administrator 用户 ID)。更大的用户 ID 中只有前 12 个字符会存储在 UserIdentifier 字段中。

  当在 WebSphere MQ for Windows 下创建消息时,AccountingToken 字段中存储一个 Windows 安全标识符 (SID)。SID 可用于补充 UserIdentifier 字段,以及用于建立用户凭据。

  PutApplName 字段长度为 28 个字符,如果路径和应用程序名称更长,则使用最后 28 个字符。

  PutTime 为 GMT 时间。

  No Context

  如果指定了消息选项 MQPMO_NO_CONTEXT,则队列管理器将在 MQPUT 时清除任何上下文字段中的任何数据。由于队列管理器不必确定要填入的值,这可以稍微提高一点速度。

  使用 No Context 不需要任何特殊的权限。

  仅当所检索的消息是使用 No Context 规格来放置的时候,PutApplType 才会为空。

  上下文处理

  放置程序可以规定应该如何填充上下文字段。可能的选项包括:

MQPMO_DEFAULT_CONTEXT队列管理器将同时提供标识上下文和来源上下文数据。
MQPMO_PASS_IDENTITY_CONTEXT队列管理器将提供来源上下文,但是将从输入消息复制标识上下文。为了使这能够正确工作,必须使用 MQOO_SAVE_ALL_CONTEXT 选项来打开输入队列,并且必须使用 MQOO_PASS_IDENTITY_CONTEXT 选项来打开输出队列。
MQPMO_PASS_ALL_CONTEXT全部八个上下文字段都可以从输入消息传递到输出消息。输入队列必须使用 MQOO_SAVE_ALL_CONTEXT 来打开,输出队列必须使用选项 MQOO_PASS_ALL_CONTEXT 来打开。
MQPMO_SET_IDENTITY_CONTEXT队列管理器将提供来源上下文,但是应用程序将设置标识上下文。输出队列必须使用选项 MQOO_SET_IDENTITY_CONTEXT 来打开。
MQPMO_SET_ALL_CONTEXT程序将控制所有上下文字段的内容。输出队列必须使用选项 MQOO_SET_ALL_CONTEXT 来打开。

  除了第一个选项外,所有这些选项都要求尝试使用它们的用户和应用程序拥有正确的权限。

  设置上下文的程序

  设置上下文的 MQPMO 选项应该仅用于特权程序。如果允许应用程序使用设置功能,则它可能会使用更高权限的用户 ID 和应用程序名称。然后在传递消息时,将会失去任何追溯实际用户和应用程序的能力。

  正如前面所指出的,上下文字段的设置和使用应该受到谨慎的控制。

  传递上下文伪代码

  清单 18 显示了用于将上下文从输入消息传递到输出消息的伪代码。


清单 18. 传递上下文示例
DEFINE OPEN_OPTIONS AS MQLONG 
DEFINE MY_IN_HANDLE AS MQHOBJ 
DEFINE MY_OUT_HANDLE AS MQHOBJ 
DEFINE MY_INPUT_QUEUE AS MQOD 
DEFINE MY_OUTPUT_QUEUE AS MQOD 
DEFINE MESSAGE_DESCRIPTOR AS MQMD 
DEFINE PUT_OPTIONS AS MQPMO 
 
CALL MQCONN(QMGR, 
      CONN_HANDLE, 
      COMP_CODE, 
      REASON_CODE) 
 
OPEN_OPTIONS = MQOO_SAVE_ALL_CONTEXT + 
        MQOO_INPUT_AS_Q_DEF 
 
MY_INPUT_QUEUE.ObjectName = 'INP1' 
 
CALL MQOPEN(CONN_HANDLE, 
      MY_INPUT_QUEUE, 
      OPEN_OPTIONS, 
      MY_IN_HANDLE, 
      COMP_CODE, 
      REASON_CODE) 
 
OPEN_OPTIONS = MQOO_PASS_ALL_CONTEXT + 
        MQOO_OUTPUT 
 
MY_OUTPUT_QUEUE.ObjectName = 'OUT1' 
 
CALL MQOPEN(CONN_HANDLE, 
      MY_OUTPUT_QUEUE, 
      OPEN_OPTIONS, 
      MY_OUT_HANDLE, 
      COMP_CODE, 
      REASON_CODE) 
 
MQGET(....) 
 
PUT_OPTIONS.Options = MQPMO_PASS_ALL_CONTEXT 
PUT_OPTIONS.Context = MY_IN_HANDLE 
 
CALL MQPUT(....) 

  此代码首先使用 MQOO_SAVE_ALL_CONTEXT 选项来打开输入队列,并使用 MQOO_PASS_ALL_CONTEXT 选项来打开输出队列。然后,在放置消息前,将放置选项设置为 MQPMO_PASS_ALL_CONTEXT,将 Context 字段设置为输入队列的对象描述符。这导致将从输入队列检索的消息的所有上下文信息传递到输出消息描述符的上下文字段。

  替代用户权限

  MQI 中的另一个安全选项是替代用户权限。替代用户权限使程序能够从输入队列获取消息,并将输入消息中上下文中的 UserIdentifier 移动到对象描述符中一个名为 MQOD_AlternateUserId 的字段。若要将此字段与 MQOPEN 一起使用,需要设置选项 MQOO_ALTERNATE_USER_AUTHORITY。或者,如果要使用 MQPUT1,则使用 MQPMO_ALTERNATE_USER_AUTHORITY 选项。

  在执行 MQOPEN 或 MQPUT1 时,将检查请求替代用户权限的发出程序权限以及 MQOD 中指定的用户 ID 权限。同时还检查 AlternateUserId 以确定它是否有权打开队列用于输入。

  消息组和分段

  简介

  消息可以出现在组中。这支持消息排序,以及较大消息在同一组中的分段。

  本部分稍后将讨论消息段。眼下只需知道段是单个物理消息,它们与相关段结合起来就构成一个逻辑消息。当必须处理对于放置或获取应用程序或队列管理器来说太大的消息时,段是非常有用的。

  逻辑消息也可以是一个物理消息。如果逻辑消息不是由段构成,那么根据定义,它就是最小的信息单元,也就是一个物理消息。

  消息组由一个或多个逻辑消息构成,并包括一个或多个具有某种关系的物理消息。稍后将探索可能的关系。

  通过使用与消息组相关联的功能,程序可以确保它以正确的顺序检索消息,而不必使用 MsgId 和 CorrelId 的某种组合。此外,它还提供了一种允许对相关消息分组的替代方法,同样无需使用 MsgId 和 CorrelId。

  至于段,它们只是处理对于程序或队列管理器(包括消息所通过的中间队列管理器)来说太大的消息的一种手段。

  消息组

  消息描述符结构中有两个字段将在处理消息组时使用:

  GroupId一个 24 字节的字段,可以包含唯一的值以标识消息组。属于特定组成员的每个逻辑消息都具有相同的 GroupId。MsgSeqNumber消息在组中的顺序;尽管 GroupId 将是相同的,但每个逻辑消息将具有不同的 MsgSeqNumber(编号从 1 开始)。

  如果消息不属于某个组,则 GroupId 将为空,而 MsgSeqNumber 将设置为 1。

  对逻辑消息分组

  创建消息组的建议方法是允许队列管理器创建唯一的 GroupId,并将其用于某个特定组中的每个消息。这是使用放置消息选项 MQPMO_LOGICAL_ORDER 和消息描述符中一个名为 MsgFlags 的字段来实现的。

  通过指定 MQPMO_LOGICAL_ORDER 并将 MsgFlags 设置为 MQMF_MSG_IN_GROUP 或 MQMG_LAST_MSG_IN_GROUP,队列管理器将为每个新组的第一个消息生成新的 GroupId。然后它将保留该 GroupId,并为该组中每个新的逻辑消息分配一个新的 MsgSeqNumber。

  如果队列管理器放置的最后一个消息包含了设置为 MQMF_LAST_MSG_IN_GROUP 的 MsgFlag,则它知道要创建新的 GroupId。由于消息组意味着将有多个消息放置在输出队列上,因此只有 MQPUT(而不是 MQPUT1)支持队列管理器的这种自动处理。

  如果应用程序希望对 MQPUT1 使用消息组,或者只是希望控制消息组的设置,则它将不使用 MQPMO_LOGICAL_ORDER 选项。如果应用程序将 GroupId 设置为 MQGI_NONE,则会生成唯一的 GroupId。然后应用程序将负责确保为该组中的每个逻辑消息分配唯一的 MsgSeqNumbers,并确保 GroupId 保持相同,直到需要新的 GroupId 为止。

  当指定了 MQPMO_LOGICAL_ORDER 时,队列管理器要求组中的消息必须全都是持久的或者全都是非持久的。如果不是这样,则调用就会失败,并产生原因代码 MQRC_INCONSISTENT_PERSISTENCE。如果未指定 MQPMO_LOGICAL_ORDER,则应用程序将负责确定是否要将持久性保持一致;队列管理器将不执行任何检查。这意味着,如果队列管理器由于任何原因而停止,并且组中混合了持久和非持久消息,则组中的有些消息可能会丢失。

  检索逻辑消息

  有两个获取消息选项可用于正确检索某个组中的逻辑消息。通过指定 MQPMO_ALL_MSGS_AVAILABLE,程序可以防止检索属于某个不完整组的消息。通过指定 MQGMO_LOGICAL_ORDER,可以按顺序返回组中的消息。此顺序可能不同于队列中消息的物理顺序。

  与 MQPUT 一样,组中消息的 MQGET 可由应用程序控制。然而,除了在系统或队列管理器发生故障后重新启动组以外,建议不要使用此方法。然后队列管理器将保留组和段信息;使用相同队列句柄的后续调用可恢复为使用 MQGMO_LOGICAL_ORDER。

  同样,只是转发物理消息的消息不应该使用 MQGMO_LOGICAL_ORDER 选项,否则可能破坏原始消息的 GroupId。

  WebSphere MQ for z/OS 支持共享和非共享队列的消息分组。此功能是通过对本地队列使用 GROUPID 的 INDXTYPE 来启用的。它在内部使用消息优先级来提供一种查找候选组并检查其完整性的高效方法。

  获取消息选项结构的 MatchOptions 字段允许程序控制要检索哪个组。如果应用程序希望检索某个特定的组,它可以将 MQGMO_LOGICAL_ORDER 选项(前提是当前没有处理任何逻辑消息)与 MatchOption MQMO_MATCH_GROUP_ID 结合使用。通过不指定 MQGMO_LOGICAL_ORDER 而指定 MatchOption MQMO_MATCH_GROUP_ID,它还可以检索具有特定 GroupId 的消息。

  MQMO_MATCH_MSG_SEQ_NUM 允许检索具有匹配 MsgSeqNumber 的特定消息。与其他 MatchOptions 一样,这是任何其他可能适用的匹配之外的附加匹配。MQMO_MATCH_MSG_SEQ_NUM 与 MQGMO_LOGICAL_ORDER 组合时无效。

  最后,通过在检索某个消息后检查获取消息选项结构中的 GroupStatus 字段,应用程序可以确定它是否已处理了某个组中的最后一个消息。如果该消息是某个组中的最后一个消息,则此字段将包含 MQGS_LAST_MSG_IN_GROUP。如不是,则此字段将包含 MQGS_MSG_IN_GROUP。

  跨工作单元

  MQPMO_LOGICAL_ORDER 选项以如下方式影响工作单元:

  如果组中的第一个消息指定了 MQPMO_SYNCPOINT,则该组中的所有后续消息都必须使用同一选项。然而,不需要在同一工作单元中放置它们。这允许将具有许多消息的消息组分散到较小的工作单元中。

  反过来,如果某个组的第一个消息已指定了 MQPMO_NO_SYNCPOINT,则该组中的所有后续消息都无法作出其他指定。

  如果不满足这些条件,则 MQPUT 将失败,并产生原因代码 MQRC_INCONSISTENT_UOW。在使用 MQGMO_SYNCPOINT 和 MQGMO_NO_SYNCPOINT 时,针对 MQPUT 描述的条件与 MQGET 相同。

  由于可以将某个组划分到多个工作单元中,因此在发生故障时,可能存在一些已提交的消息和一些未提交的消息。跟踪与跨工作单元的组关联的状态信息是应用程序的责任。通过跟踪特殊状态队列上的 GroupId 和 MsgSeqNumber(使用 MQPUT 和 MQGET 的同步点选项),可以保存关于已完成工作的准确状况。

  正如前面所讨论过的,如果进行了重新启动,这就是可以使用的信息,而无需指定获取或放置消息选项来获得本质地重新开始某个组的队列处理的逻辑顺序。

  消息分段

  前面对消息段的定义是相当简略的,现在我们将更详细地探索它们。本讨论假设所有 MQPUT 和 MQGET 工作都在一个工作单元内操作。强烈建议将这作为标准实践,以避免网络中存在不完整分段的消息的任何可能性。

  分段消息使用消息描述符中一个名为 Offset 的字段,描述某个特定段的数据将在完整逻辑消息中的何处开始。

  分段消息的放置和获取可以在队列管理器或应用程序的控制下进行。

  队列管理器进行的分段

  如果消息描述符中的 MsgFlag 字段包括值 MQMF_SEGMENTATION_ALLOWED,则队列管理器将处理分段消息的构建。如果队列管理器认识到消息大于其 MaxMsgLength 或队列的 MaxMsgLength,则会执行分段。

  如果消息描述符包括 MQRO_..._WITH_DATA 选项,则会对其进行修改,以消除对没有包括前 100 个字节的任何段上的数据请求。

  由于队列管理器处理段的划分,因此无法作出关于如何划分数据的假设。

  持久消息分段只能在一个工作单元内执行。如果队列管理器确定不存在应用程序定义的活动工作单元,则队列管理器将创建一个工作单元,此工作单元仅在调用的持续时间内活动。

  队列管理器进行的重新组装

  为了检索完整的分段消息,应用程序设置选项 MQGMO_COMPLETE_MESSAGE。如果队列管理器确定消息是分段的,它将检索所有段,并在程序的缓冲区中返回完整的消息。

  数据转换是在将消息放到程序缓冲区之后进行的,因此这与分段消息并没有任何不同。然而对于消息段,发送方通道请求的数据转换将会失败,因为出口没有一次获得消息中的所有数据。

  如果队列管理器确定消息是持久消息,并且不存在用户定义的工作单元,则队列管理器将创建一个在调用持续时间内有效的工作单元。它不会自动为非持久消息创建工作单元。

  应用程序进行的分段

  应用程序分段用于两个目的:

  队列管理器分段不够,因为应用程序缓冲区不够大,无法处理整个消息。

  发送方通道必须处理数据转换,并且放置程序需要在特定的边界上划分消息,以支持成功的段转换。

  应用程序应该使用放置消息选项 MQPMO_LOGICAL_ORDER,并将消息描述符中的 MsgFlags 字段设置为 MQMF_SEGMENT 或 MQMG_SEGMENT_LAST。队列管理器将分配并维护 GroupId、MsgSeqNumber 和 Offset 字段。

  正如前面在关于消息组的介绍中所讨论的,如果应用程序没有指定 MQPMO_LOGICAL_ORDER 选项,则程序将负责确保分配新的 GroupId,以及分配正确的 MsgSeqNumbers 和 Offsets。

  正如在讨论消息组时所指出的,允许放置和获取跨工作单元的消息。

  应用程序进行的重新组装

  可以指定 MQGMO_COMPLETE_MESSAGE_OPTION 和 MQMF_SEGMENTATION_ALLOWED MsgFlag 以使队列管理器能够检索由应用程序分段的消息。

  如果应用程序选择单独检索各个段,最可能的原因是受到缓冲区大小的限制,因此需要有在应用程序控制下重新组装消息的功能。

  如果程序指定 MQGMO_ALL_MSGS_AVAILABLE 或 MQGMO_ALL_SEGMENTS_AVAILABLE 作为其获取消息选项之一,如果所有消息段都不可用,则处理将不会发生。包括 MQGMO_WAIT(带等待间隔)来为所有段的到达留出时间是有意义的。

  一旦检索到第一个消息,则使用 MQGMO_LOGICAL_ORDER 选项来确保处理消息的所有其余段。

  可以不指定 MQGMO_LOGICAL_ORDER 以用于恢复目的,前面讨论的消息组就是这样。唯一的附加要求是需要跟踪段的 Offset 以及 GroupId 和 MsgSeqNumber。

  任何只是传递数据的中间应用程序都不应该使用 MQGMO_LOGICAL_ORDER 选项,以确保 Offset 不会受到破坏。

  MatchOptions 字段还用于检索消息段。除了 MQMO_MATCH_GROUP_ID 和 MQMO_MATCH_MSG_SEQ_NUM 选项外,还可以将 MatchOptions 设置为 MQMO_MATCH_OFFSET。

  通过在检索某个消息段之后检查获取消息选项结构的 SegmentStatus,应用程序可以确定它是否已处理了消息的最后一个段。如果该消息是分段消息中的最后一个消息,则此字段将包含 MQSS_LAST_SEGMENT。如不是,则此字段将包含 MQSS_SEGMENT。

  分发列表

  概述

  分发列表允许您在单个 MQPUT 或 MQPUT1 调用中将消息放置到多个目标。可以使用单个 MQOPEN 来打开多个队列,然后可以使用单个 MQPUT 来将消息放置到那些队列中的每个队列。MQI 结构中用于此过程的一些通用信息可由与分发列表中的各个目标关联的特定信息取代。

  打开分发列表

  对象记录 (MQOR) 结构用于提供分发列表中每个目标的 ObjectName 和 ObjecQMgrName。对象描述符 (MQOD) 中的字段 RecsPresent 指示正在使用某个分发列表。如果 RecsPresent 大于零,则它包含分发列表中的对象记录数量。

  对象描述符中有两个指向对象记录的字段:ObjectRecOffset 和 ObjectRecPtr。这些字段是相互排斥的。

  ObjectRecOffset 是第一个 MQOR 相对于对象描述符开头的偏移。此方法有利于不支持指针数据类型或实现指针数据类型的方法在环境之间不可移植(例如,COBOL)的编程语言。

  ObjectRecPtr 是指向 MQOR 数组开头的指针。建议对以可移植的方式支持指针数据类型的编程语言(例如 C 语言)使用此方法。

  每个 MQOR 中的 ObjectName 是队列名称,而且一定不能是模型队列ObjectQMgrName 是队列所在的队列管理器的名称。请注意,MQOD 是由应用程序构建的;分发列表不是管理员定义的 WebSphere MQ 对象。

  在为分发列表中的所有队列构建 MQOR 并为对象描述符设置 RecsPresent 与 ObjectRecOffset 或 ObjectRecPtr 时,将发出 MQOPEN。

  每个目标队列都单独地打开,意味着有些可能成功,其他无效的则会失败。如果所有队列都成功打开,则从 MQOPEN 返回的完成代码将是 MQCC_OK。如果所有队列都未能打开,则完成代码将是 MQCC_FAILED。然而,如果有些队列成功打开而有些队列未能打开,则完成代码将是 MQCC_WARNING。对于失败和警告,原因代码都将是 MQRC_MULTIPLE_REASONS。

  对象描述符中的三个 *_DEST_COUNT 字段将在 MQOPEN 后被更新:

KnownDestCount成功打开的本地队列数量。
UnknownDestCount成功打开的远程队列数量。
InvalidDestCount未能成功打开的队列数量。

  所打开的每个队列的完成代码和原因代码将在一个称为响应记录 (MQRR) 的结构中返回。与前面的对象记录一样,对象描述符的 RecsPresent 字段给出响应记录的数量。而且与前面一样,有两种对 MQRR 数组寻址的方法:定义偏移的 ResponseRecOffset 或指向地址的 ResponseRecPtr。MQRR 记录和偏移或指针必须在调用 MQOPEN 之前设置。

  向分发列表添加消息

  放置消息选项 (MQPMO) 结构中有几个字段与分发列表相关。

  PutmsgRecFields 包括标志,指示放置消息记录 (MQPMR) 结构中存在哪些字段。可以指定一个或多个标志:

MQPMRF_MSG_ID消息标识符
MQPMRF_CORREL_ID相关性标识符
MQPMRF_GROUP_ID组标识符
MQPMRF_FEEDBACK反馈
MQPMRF_ACCOUNTING_TOKEN记帐令牌
MQPMRF_NONE不存在放置消息记录

  RecsPresent 字段提供放置消息记录的数量计数。PutMsgRecOffset 和 PutMsgRecPtr 分别提供第一个放置消息记录的偏移或第一个放置消息记录的地址,并且是相互排斥的。如果不存在放置消息记录,则两个字段都应该包含零。

  放置消息记录 (MQPMR) 结构最多可以包含五个字段:

MsgId将用于发送到如下队列的消息的消息标识符,该队列的名称由 MQOPEN 或 MQPUT1 调用上提供的 MQOR 结构数组中的对应元素所指定。对于那些没有包含 MsgId 的 MQPMR,则使用消息描述符 MsgId 字段中的值。如果该值为 MQMI_NONE,则为那些目标中的每一个生成唯一的 MsgId(不会有两个目标具有相同的 MsgId)。如果指定了 MQPMO_NEW_MSG_ID,则为分发列表上的每个目标生成新的 MsgId,而不管它们是否有 MQPMR 记录。
CorrelId将用于发送到如下队列的消息的相关性标识符,该队列的名称由 MQOPEN 或 MQPUT1 调用上提供的 MQOR 结构数组中的对应元素所指定。如果此字段不存在,或者 MQPMR 比目标少,则使用消息描述符的 CorrelId 字段。如果指定了 MQPMO_NEW_CORREL_ID,则生成单个新的相关性标识符,并用于分发列表中的所有消息。
GroupId将用于发送到如下队列的消息的组标识符,该队列的名称由 MQOPEN 或 MQPUT1 调用上提供的 MQOR 结构数组中的对应元素所指定。消息描述符的 GroupId 的使用方式与上面对 MsgId 和 CorrelId 描述的条件相同。
Feedback用于发送到如下队列的消息,该队列的名称由 MQOPEN 或 MQPUT1 调用上提供的 MQOR 结构数组中的对应元素所指定。如果不存在,则使用消息描述符的 Feedback 字段。
AccountingToken用于发送到如下队列的消息,该队列的名称由 MQOPEN 或 MQPUT1 调用上提供的 MQOR 结构数组中的对应元素所指定。如果不存在,则使用消息描述符的 AccountingToken 字段。

  正如在用于分发列表的 MQOPEN 中所描述的,同样的情况也适用于 MQPUT。仅当所有放置都成功时,才会返回 MQCC_OK。仅当所有放置都失败时,才会返回 MQCC_FAILED,并在有些成功而有些失败时返回 MQCC_WARNING。如果返回 MQCC_WARNING 或 MQCC_FAILED,则原因代码将为 MQRC_MULTIPLE_REASONS。

  每个队列的响应记录将包含针对该队列的放置操作的完成代码和原因代码。由于队列管理器对每个队列发出一个单独的 MQPUT,因此单独跟踪每个放置操作是可能的。

  MQPMO 结构的 KnownDestCount、UnknownDestCount 和 InvalidDestCount 字段分别提供成功发送到本地队列的消息、成功发送到远程队列的消息和未能成功发送的消息的计数。

  尝试进行的每个放置操作的完成代码和原因代码将在一个称为响应记录 (MQRR) 的结构中返回。MQPMO 结构的 RecsPresent 字段给出响应记录数量。而且与前面一样,有两种对 MQRR 数组寻址的方法:定义偏移的 ResponseRecOffset 或指向地址的 ResponseRecPtr。MQRR 记录和偏移或指针必须在调用 MQOPEN 之前设置。

  关闭分发列表

  关闭分发列表时,除 MQCO_NONE 以外的任何关闭选项都将产生原因代码 MQRC_OPTION_NOT_VALID_FOR_TYPE 或 MQRC_OPTIONS_ERROR。

  只有 MQCLOSE 的完成代码和原因代码可用于诊断目的。不返回任何单独的完成代码和原因代码,并且不标识任何遇到错误的队列。即使可能发生故障,队列管理器也会继续处理,并尝试关闭分发列表中的其余队列。

  分发列表示例代码

  在本部分,我们将查看并运行一些示例代码来演示分发列表的使用。

  检查示例代码

  让我们首先看一下如清单 19 所示的配置文件,您将运行它来设置分发列表的队列。


清单 19. setup05.txt 配置文件
DEFINE QLOCAL('CERT.LIST1') REPLACE 
 
DEFINE QLOCAL('CERT.LIST2') REPLACE 
 
DEFINE QLOCAL('CERT.LIST3') REPLACE 
 
DEFINE QLOCAL('CERT.LIST4') REPLACE + 
  PUT(DISABLED) 

  此配置文件只是创建四个队列 CERT.LIST1-4,但是在 CERT.LIST4 上禁用了消息放置。

  DistLists.java 创建一个分发列表,打开它,并在其上放置单个消息。然后它报告为每个队列返回的完成和原因代码。与以前一样,该操作发生在 run() 方法中,因此我们首先看一下该方法的前几行,如下所示。


清单 20. run() 方法的开头
  public void run() { 
 
   System.out.println("Start DistList"); 
 
   try { 
 
     MQQueueManager qMgr = new MQQueueManager(qManager); 
 
     MQDistributionListItem item1 = new MQDistributionListItem(); 
     item1.queueManagerName = qManager; 
     item1.queueName = item1Name; 
     MQDistributionListItem item2 = new MQDistributionListItem(); 
     item2.queueManagerName = qManager; 
     item2.queueName = item2Name; 
     MQDistributionListItem item3 = new MQDistributionListItem(); 
     item3.queueManagerName = qManager; 
     item3.queueName = item3Name; 
     MQDistributionListItem item4 = new MQDistributionListItem(); 
     item4.queueManagerName = qManager; 
     item4.queueName = item4Name; 
 
     MQDistributionListItem[] items = { item1, item2, item3, item4 }; 
 
     int openOptions = MQC.MQOO_OUTPUT + MQC.MQOO_FAIL_IF_QUIESCING; 
 
     MQDistributionList distList = new MQDistributionList(qMgr, items, 
        openOptions, null); 
 

  与 MQOR 和 MQRR 结构一样,WebSphere MQ base Java 类提供 MQDistributionListItem 和 MQDistributionList 类,这些类提供了与那些结构相似的功能。此代码创建并初始化 MQDistributionListItem,然后将它们放在作为 MQDistributionList 构造函数参数的数组中。构造一个 MQDistributionList 与打开一个分发列表相同。

  因此,这里的代码演示了连接到队列管理器、创建四个分发列表项,然后将它们放到一个数组中。此外还对打开选项进行了初始化并创建了分发列表。

  清单 21 显示了如何创建一个消息并将其放置到分发列表。


清单 21. 将消息放置到分发列表
     String message = "A message sent to a distribution list"; 
 
     MQPutMessageOptions putOptions = new MQPutMessageOptions(); 
     putOptions.options = MQC.MQPMO_NO_SYNCPOINT 
        + MQC.MQPMO_FAIL_IF_QUIESCING; 
 
     MQMessage msg = new MQMessage(); 
     msg.messageType = MQC.MQMT_DATAGRAM; 
     msg.writeUTF(message); 
     msg.format = MQC.MQFMT_STRING; 
     msg.messageId = MQC.MQMI_NONE; 
     msg.correlationId = MQC.MQCI_NONE; 
 
     try { 
 
      distList.put(msg, putOptions); 

  此代码看起来应该是非常熟悉的。它与其他示例程序中的放置之间的唯一区别是使用了分发列表对象上的 put() 方法。还要注意,Put 在它自己的 try 块中,因此您可以仅捕获该 Put 中的错误。

  清单 22 显示了 Put 的错误处理代码。


清单 22. Put 的错误处理
     } catch (MQException mqex) { 
      if (mqex.completionCode == MQException.MQCC_WARNING) { 
        MQDistributionListItem item = distList 
           .getFirstDistributionListItem(); 
        while (item != null) { 
         System.out 
            .println("Error for queue: " + item.queueName); 
         System.out.println("Completion code: " 
            + item.completionCode); 
         System.out.println("Reason code: " + item.reasonCode); 
         item = item.getNextDistributedItem(); 
        } 
      } else { 
        System.out 
           .println("A WebSphere MQ Error occured : Completion Code " 
              + mqex.completionCode 
              + " Reason Code " 
              + mqex.reasonCode); 
        mqex.printStackTrace(); 
      } 
     } 

  该错误处理代码首先检查 MQCC_WARNING。这告诉它有些放置成功而有些则失败。然后它遍历分发列表项,检索并显示队列名称、完成代码和原因代码。WebSphere MQ base Java 类在分发列表上提供了两个方法来代替 Offset 或 Ptr 变量,以协助遍历该列表:getFirstDistributionListItem() 和 getNextDistributionListItem()。

  下面的清单 23 显示了该程序的结尾:关闭分发列表,程序断开与队列管理器的连接,并向控制台打印一条指示程序结束的消息。清单 23 还显示了最外层 try 块中的 catch。


清单 23. 程序结束和异常处理
     distList.close(); 
 
     qMgr.disconnect(); 
 
     System.out.println("End DistList"); 
 
   } catch (MQException mqex) { 
     System.out 
        .println("A WebSphere MQ Error occured : Completion Code " 
           + mqex.completionCode + " Reason Code " 
           + mqex.reasonCode); 
     mqex.printStackTrace(); 
   } catch (IOException e) { 
     e.printStackTrace(); 
   } 
  } 
} 

  运行示例代码

  现在您可以设置分发列表队列并运行示例代码。.

  打开一个 Windows 命令提示符。

  键入 runmqsc < setup05.txt

  关闭 Windows 命令提示符。

  在 Application Developer 中,在 Package Explorer 视图中右键单击 DistList.java,并选择 Run > Java Application。

  当程序完成运行时,控制台应该与图 8 类似。


图 8. DistList.java 的控制台
WebSphere MQ Solution Designer 认证考试 996 准备: 第 5 部分,其他 MQI 主题(下)


  完成代码 0 表示 MQCC_OK,原因代码 0 表示 MQRC_NONE。那些值是为列表中的前三个队列返回的。完成代码 2 表示 MQCC_FAILED,原因代码 2051 表示 MQCC_PUT_INHIBITED。这就是您对 CERT.LIST4 所获取的确切结果,并且就是您预期的内容,因为该队列是在禁用 Put 的情况下创建的。

  使用 WebSphere Explorer 来浏览 CERT.LIST1、CERT.LIST2、CERT.LIST3 和 CERT.LIST4 中的消息(其中应该没有消息)。

  结束语

  本教程结束了前一教程中开始的 MQI 讨论,并介绍了 MQINQ、MQSET、事务、触发、安全性、消息组和段以及分发列表。完成本系列中的五个教程可以帮助您获得所需的知识以准备考试 996:IBM WebSphere MQ V6.0, Solution Design,但是决不取代您通过使用产品和学习文档所获得的经验和知识。

  但愿您会发现本教程是有帮助的,并祝您在准备认证考试时获得好运。

  本文示例源代码或素材下载

编缉推荐阅读以下文章

  • WebSphere MQ Solution Designer 认证考试 996 准备: 第 5 部分,其他 MQI 主题(上)
  • WebSphere MQ Solution Designer 认证考试 996 准备: 第 4 部分,主要 MQI 调用(下)
  • WebSphere MQ Solution Designer 认证考试 996 准备: 第 4 部分,主要 MQI 调用(上)
  • WebSphere MQ Solution Designer 认证考试 996 准备: 第 3 部分,分布式队列管理(下)
  • WebSphere MQ Solution Designer 认证考试 996 准备: 第 3 部分,分布式队列管理(上)
  • WebSphere MQ Solution Designer 认证考试 996 准备: 第 2 部分:安装和配置(下)
  • WebSphere MQ Solution Designer 认证考试 996 准备: 第 2 部分:安装和配置(上)
  • WebSphere MQ Solution Designer 认证考试 996 准备: 第 1 部分:简介和概述(下)
  • WebSphere MQ Solution Designer 认证考试 996 准备: 第 1 部分:简介和概述(上)

本文来自[教育资源网]edu.5151doc.com收集与整理,感谢原作者。
本文版权归原作者所有,如需转载或摘录请注明出处:教育资源网 http://edu.5151doc.com

文章录入:魅力教师    责任编辑:5151doc 
【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
| 设为首页 | 加入收藏 | 联系站长 | 在线投稿 | 版权申明 | 网站登陆 |