MQ/204 messages

From m204wiki
Jump to navigation Jump to search

Grouping messages

MQ/204 takes advantage of the new features IBM introduced for WebSphere MQSeries, in particular the grouping of messages. The new fields in the MQMD Version 2 are Group ID and status, sequence number and flags. The Group ID, sequence number, and some of the flags determine whether a message is part of a group. Now Model 204 users can control the grouping of messages.

The other fields that apply to segmentation are not covered, because the segmentation options are not available for z/OS.

Supporting Java Message Service (JMS)

MQ/204 supports the predefined JMS protocol. MQ/204 now understands and can talk to Java through the messaging services. The JMS protocol, when sending MQ messages, expects to encode certain Java-specific fields into the additional header known as the MQRFH Version 2 (MQRFH2) header. The receiving mainframe application should expect to receive such a header, if it knows that the source of the messages is a JMS application.

Because the MQRFH2 header carries JMS-specific information, always include it in the message when you know that the receiving destination is a JMS application.

Conversely, omit the MQRFH2 when sending a message directly to a non-JMS application, because such an application does not expect an MQRFH2 in its WebSphere MQ message.

Environment requirements

Minimum is Model 204 V7R1.0.

Consulting IBM documentation

Rocket recommends that you keep these documents handy:

  • IBM Application Programming Reference
  • IBM MQ manual, Using Java

Message groups

You can group messages together. Each message in a group has its own sequence number and shares the group ID number. The sequence number is assigned by system or by you, depending on whether you select the LOGICAL_ORDER or NOT_LOGICAL_ORDER option on your command or statement.

  • The physical order of the messages in the group is the order in which the messages were written and that order is retained using the LOGICAL_ORDER option, so that the physical and logical order of the messages in the group match.
  • You can set the logical order of the messages in the group using the NOT_LOGICAL_ORDER and the SEQUENCE option. The physical and logical order of the messages in the group may differ, as you assigned the sequence numbers.

In either case, the messages in the group are processed in ascending order and the highest sequence number in the group is called the last logical message.

When you use MQPUT to write messages, you have three options, which are discussed in turn:

  • Group messages in logical order
  • Group messages, but not in logical order
  • Do not group messages

Messages grouped in logical order

Grouping messages in logical order is the more simple way of writing messages that are in a group.

  1. On the first message you set the options:
    • GSTATUS='G'
    • LOGICAL_ORDER

    There is no need to set GROUPID or SEQUENCE, as the queue manager automatically assigns these values.

  2. Continue writing messages to the queue with GSTATUS='G' and LOGICAL_ORDER options set until the last logical message.
  3. For the last message you set the options:
    • GSTATUS='L'.
    • LOGICAL_ORDER

Using this method, you can write messages to only one group at a time.

Message groups and MQPUT1

The LOGICAL_ORDER option is not allowed on the MQPUT1 statement, although the GSTATUS, SEQUENCE, and GROUPID options are allowed, so it is possible to write a message to a group using MQPUT1, but not in logical order.

Messages grouped, not in logical order

You might need to group messages but cannot use the LOGICAL_ORDER option because either you need to write...

  • ...to two or more groups at the same time
  • ...messages where the physical sequence is not also the logical sequence. (You are not writing the messages in ascending order of sequence number.)

Grouping messages, but not in logical order, is more complex to handle, but gives you more flexibility. To group messages this way:

  1. On the first message you must set the options:
    • GSTATUS to 'G', unless this is the last logical message in the group--the highest sequence number--in which case set GSTATUS to 'L'.
    • NOT_LOGICAL_ORDER
    • GROUPID to null or spaces
    • SEQUENCE to the sequence number of this message within the group, which must be greater than zero, although not necessarily one, because the messages can be out of sequence.
  2. When this first MQPUT to the queue completes, you must save the GROUPID returned in the DESCRIPTOR field, because this is the Group ID that the queue manager has assigned to this group. You will set this for all subsequent messages in this group.
  3. For all subsequent messages in the group set the options:
    • GSTATUS='G', unless this is the last logical message in the group--the highest sequence number--in which case set GSTATUS='L'.
    • GROUPID to the value returned from the first MQPUT (step 2)
    • NOT_LOGICAL_ORDER
    • SEQUENCE to the sequence of this message within the group.

If you write groups in this way, you can write to several groups at the same time. Be careful to save all the Group ID values from the first MQPUT for each group.

Messages not grouped

Messages not grouped was the only available behavior in MQ/204 V6R1.0 and earlier. You can maintain previous behavior by omitting GSTATUS or setting it to null or space (' '). The settings for SEQUENCE, GROUPID and LOGICAL_ORDER options are ignored.

Searching for messages using the MATCH options

You can retrieve messages that match criteria that you specify. The new options for the MQGET statement are:

MATCH_CORREL_ID or NOT_MATCH_CORREL_ID MATCH_GROUP_ID MATCH_MSG_ID or NOT_MATCH_MSG_ID MATCH_MSG_SEQ_NUMBER MATCH_MSG_TOKEN

Although these options are new, the behavior prior to MQ/204 V6R2.0 was to match on any supplied CORRELID and MSGID. To avoid upward compatibility issues, the MQ/204 V6R2.0 defaults are:

MATCH_CORREL_ID MATCH_MSG_ID

There are no equivalent NOT_ options for the criteria of GROUPID, SEQUENCE, and MSGTOKEN, because simply omitting these MATCH_ options reverses their effect.

Before searching for and retrieving messages

To search and retrieve messages using the MATCH options, you must know the index type of the queue. The index type of the queue was set by the system manager when the queue was defined.

The following table lists the index types, their purpose, and usage.

Index types and purpose
Index type Queue manager maintains For queues
CORRELID Correlation identifiers of the messages on the queue. Where the application usually retrieves messages using the correlation identifier as the selection criterion on the MQGET call.
GROUPID Group identifiers of the messages on the queue. Where the application retrieves messages using the LOGICAL_ORDER option on the MQGET call.
MSGID Message identifiers of the messages on the queue. Where the application usually retrieves messages using the message identifier as the selection criterion on the MQGET call.
MSGTOKEN Message tokens of the messages on the queue for use with the workload manager (WLM) functions of z/OS. That are WLM-managed queues; do not specify it for any other type of queue. Also, do not use this value for a queue where an application is not using the z/OS workload manager functions, but is retrieving messages using the message token as a selection criterion on the MQGET call.
No index No index. That are usually processed sequentially, that is, without using any selection criteria on the MQGET call.

Using index types with message groups

The following table, "Index types and NOT_LOGICAL_ORDER option," and the next table, "Index types and LOGICAL_ORDER option," list the search criteria you can use when a queue is defined with particular index type(s). Since you can retrieve messages in logical order or not logical order, your MQGET statement can also include either the NOT_LOGICAL_ORDER or LOGICAL_ORDER option.

Index types and NOT_LOGICAL_ORDER option
Selection criteria on MQGET call Index type for nonshared queue Index type for shared queue
None Any Any
Selection using one MATCH_ option
MSGID MSGID recommended None or MSGID
CORRELID CORRELID recommended CORRELID required
GROUPID GROUPID recommended GROUPID required

Selection using two MATCH_ options

MSGID + CORRELID MSGID or CORRELID recommended MSGID or CORRELID required
MSGID + GROUPID MSGID or GROUPID recommended Not supported
CORRELID + GROUPID CORRELID or GROUPID recommended Not supported
Selection using three MATCH_ OPTIONS
MSGID + CORRELID + GROUPID MSGID or CORRELID or GROUPID recommended Not supported
Selections using group-related criteria
GROUPID + SEQUENCE GROUPID required GROUPID required
SEQUENCE (must be at least one) GROUPID required GROUPID required
Selection using MSGTOKEN
For application use Do not index by MSGTOKEN Do not index by MSGTOKEN
For Work Load Management (WLM) use MSGTOKEN required Not supported

The following table lists the required index type when LOGICAL_ORDER is specified on a shared or not-shared queue.

Index type and LOGICAL_ORDER option
Selection criteria on MQGET call Index type for nonshared queue Index type for shared queue
None GROUPID required GROUPID required
Selection using one MATCH_ option
MSGID GROUPID required Not supported
CORRELID GROUPID required Not supported
GROUPID GROUPID required GROUPID required
Selection using two MATCH_ options
MSGID + CORRELID GROUPID required Not supported
MSGID + GROUPID GROUPID required Not supported
CORRELID + GROUPID GROUPID required Not supported
Selection using three MATCH_ options
MSGID + CORRELID + GROUPID GROUPID required Not supported

Retrieving messages not grouped

If there is no current group or logical message, only messages that have SEQUENCE=1 are eligible for return. In this situation, one or more of the following match options can be used to select which of the eligible messages is the one actually returned:

  • MATCH_CORREL_ID
  • MATCH_GROUP_ID
  • MATCH_MSG_ID

If LOGICAL_ORDER is specified, and there is a current group, only the next message in the group is eligible for return, and this cannot be altered by specifying MATCH_ options.

Match options which are not applicable can still be specified, but the value of the relevant field must match the value of the corresponding field in the message to be returned.

One or more of the following match options can be specified.

Using the MATCH options
MATCH_ option Retrieves message with specified... Message retrieved must have...
CORREL_ID Correlation identifier Correlation identifier that matches the value of CORRELID, as well as any other matches that may apply, such as message identifier.

If NOT_MATCH_ option is specified, the CORRELID field is ignored and any correlation identifier will match.

GROUP_ID Group identifier Group identifier that matches the value of GROUPID, as well as any other matches that may apply, such as correlation identifier.
MSG_ID Message identifier Message identifier that matches the value of MSGID, as well as any other matches that may apply, such as correlation identifier.

If NOT_MATCH_ option is specified, MSGID is ignored and any message identifier will match.

MSG_SEQ_NUMBER Message sequence number Message sequence number that matches the value of the SEQUENCE field, as well as any other matches, such as group identifier.
MSG_TOKEN Message token Message token that matches the value of MSGTOKEN--only for queues that have an index type of MSGTOKEN. You cannot specify other match options with MATCH_MSG_TOKEN.

BROWSE options

For MQ/204 after V6R1.0, there are new options for browsing a queue.

BROWSE_MSG_UNDER_CURSOR, a new option on the MQGET statement, lets you reread the same message. You can combine this option with the LOCK or UNLOCK options.

  • LOCK option lets you lock a message so that another thread cannot browse it. The lock is automatically released at the end of the unit of work, even if there is no explicit UNLOCK. The LOCK option is also valid with BROWSE_FIRST and BROWSE_NEXT.
  • UNLOCK option causes the message to be unlocked without retrieving the message.
  • Omitting both LOCK and UNLOCK options unlocks the message, but also retrieves it again.

    The following sequence of calls is an example:

    MQGET BROWSE_FIRST MQGET BROWSE_NEXT /*until the required message is found MQGET BROWSE_MSG_UNDER_CURSOR LOCK /* to reread the last message and lock it MQGET BROWSE_MSG_UNDER_CURSOR UNLOCK /* unlock the same message without retrieving it again

Special handling options

ALL_MSGS_AVAILABLE option

You can specify the new ALL_MSGS_ AVAILABLE option on the MQGET statement, and you can set it as a default for the queue by specifying ALL_MSGS_AVAILABLE on the DEFINE QUEUE command or MODIFY QUEUE statement. The default setting is NOT_ALL_MSGS_AVAILABLE.

If ALL_MSGS_AVAILABLE is specified, a message that is part of a group cannot be retrieved from the queue unless all messages in the group are available for retrieval.

MSGTOKEN option

The 16-byte message token, like the message ID, identifies a message as unique. However, unlike the message ID, the message token is not passed between queue managers, so a message token changes as it passes from one queue manager to another queue manager.

You can retrieve the MSGTOKEN %variable option on a MQGET statement. It is also an input field on the MQGET statement, if you also specified the MATCH_MSG_TOKEN option.

NEW_CORREL_ID option

The NEW_CORREL_ID option on the MQPUT and MQPUT1 statements tells the queue manager to generate a new correlation ID for the message. The CORRELID option should not be specified with this field, because the queue manager generates a unique correlation identifier, rather than taking it from the CORRELID field.

SYNCPOINT_IF_PERSISTENT option

The SYNCPOINT_IF_PERSISTENT option is like the SYNCPOINT option, although the request is under transaction control (affected by MQCMIT and MQBACK statements) only if the message is PERSISTENT. This option is valid only on the MQGET statement.

Examples of writing messages and browsing groups

Example of writing messages to a group in logical order

The following example writes messages to a group in logical order. Note that it is unnecessary to specify SEQUENCE or GROUPID.

%QNAME IS STRING LEN 8 %MSG2 IS STRING LEN 100 %MSG1 IS STRING LEN 100 %MSGID IS STRING LEN 24 %COUNT IS FIXED %LO = 'LOGICAL_ORDER' %MSG1 = 'PUTS 4 MESSAGES IN A LOGICALLY ORDERED GROUP' %COUNT = 0 %GSTAT = 'G' /? group status for first four messages?/ OPEN QUEUE %QNAME OUTPUT REPEAT 3 TIMES %COUNT = %COUNT + 1 %MSG2 = %MSG1 WITH %COUNT MQPUT %MSG2 ON %QNAME GSTATUS %GSTAT LOGICAL_ORDER CALL PRINT.STATUS /? test return codes ?/ END REPEAT %GSTAT = 'L' /? group status for last message only ?/ %COUNT = %COUNT + 1 %MSG2 = %MSG1 WITH %COUNT MQPUT %MSG2 ON %QNAME GSTATUS %GSTAT  ?%LO /? logical order specified as runtime option ?/

Example of writing messages to a group out of sequence

The following example writes messages to a group out of sequence. Notice that we specify NOT_LOGICAL_ORDER, and take care to set SEQUENCE, GSTATUS, and GROUPID correctly.

%MSG1 = '5 MESSAGES IN A GROUP OUT OF SEQUENCE' %COUNT = 0 * imbed the image definition for the message descriptor I MQMDV2 PREPARE IMAGE MQMD %NLO = 'NOT_LOGICAL_ORDER' * for the first physical PUT, the group must be null %GRP = ' ' * GSTATUS must be L for the last logical message %GSTAT = 'L' /? group status for SEQUENCE = 5 ?/ OPEN QUEUE %QNAME OUTPUT %SEQ = 5 * we can write the message with sequence number 5 first REPEAT 4 TIMES %COUNT = %COUNT + 1 %MSG2 = %MSG1 WITH %COUNT * specify DESCRIPTOR to retrieve the GROUPID MQPUT %MSG2 ON %QNAME GSTATUS %GSTAT - SEQUENCE %SEQ /? this group in reverse order of sequence ?/ - NOT_LOGICAL_ORDER - GROUPID %GRP /? null for first PUT, then generated GROUPID ?/ - DESCRIPTOR MQMD /? needed to retrieve generated GROUPID ?/ %SEQ = %SEQ - 1 /? next PUT will have lower SEQUENCE ?/ CALL PRINT.STATUS /? always check the return code ?/ * GSTATUS must be G for all other messages %GSTAT = 'G' /? group status for SEQUENCE 1 to 4 ?/ %GRP = $MQMD:GROUPID /? retrieve the generated GROUPID ?/ PRINT 'Generated GROUPID IS: ' WITH %GRP END REPEAT %COUNT = %COUNT + 1 %MSG2 = %MSG1 WITH %COUNT MQPUT %MSG2 ON %QNAME GSTATUS %GSTAT - SEQUENCE %SEQ /? last PUT has SEQUENCE 1 in this example ?/ -  ?%NLO GROUPID %GRP /? use generated GROUPID for last time ?/ CALL PRINT.STATUS

Browsing a group of messages

This example browses a group of messages. In this case we are using the option MATCH_GROUP_ID to select messages in a certain group, and LOGICAL_ORDER to ensure that we retrieve them in sequence number order. The index type for this queue must therefore be GROUPID.

%QN IS STRING LEN 8 %MG = 'MATCH_GROUP_ID' %GI = 'GROUPID %GRP' %LO = 'LOGICAL_ORDER' INCLUDE MQMD /? image definition of V2 message descriptor ?/ %COUNT IS FIXED %TEXT IS STRING LEN 255 %GRP IS STRING LEN 24 %MSGID IS STRING LEN 24 %MSGTOKEN IS STRING LEN 16 %CORRELID IS STRING LEN 24 %GSTAT IS STRING LEN 1 %SEQ IS FIXED * you can specify LOGICAL_ORDER on OPEN or MODIFY OPEN QUEUE %QN BROWSE %LO CALL PRINT.STATUS /? always check the return code ?/ %COUNT = 0 MQGET %TEXT FROM %QN NO_WAIT - BROWSE_FIRST - DESCRIPTOR MQMD /? retrieve group ID ?/ CALL PRINT.STATUS %GRP = %MQMD:GROUPID /? save these values from ?/ %SEQ = %MQMD:MSGSEQNO /? the message descriptor ?/ %MSGID = %MQMD:MSGID %CORRELID = %MQMD:CORRELID * NOW READ THE WHOLE QUEUE USING THE 'MATCH' KEYWORD MQGET %TEXT FROM %QN NO_WAIT - BROWSE_FIRST ?%MG /? MATCH_GROUP_ID can be a runtime var ?/ -  ?%GI /? GROUPID %GRP is another run-time variable ?/ - DESCRIPTOR MQMD CALL PRINT.STATUS %COUNT = %COUNT + 1 READ.NEXT: MQGET %TEXT FROM %QN NO_WAIT -  ?%MG ?%GI - BROWSE_NEXT - DESCRIPTOR MQMD GSTATUS %GSTAT CALL PRINT.STATUS IF $STATUS = 23 THEN JUMP TO END.LOOP /? end if no more messages in the group ?/ END IF IF $STATUS = 12 THEN JUMP TO END.LOOP /? test for other errors ?/ END IF %COUNT = %COUNT + 1 /? count messages in the group ?/ * It would also be possible to test for %GSTAT = 'L' to test for * the end of the loop, as here: IF %GSTAT = 'L' /? last message in the group ?/ JUMP TO END.LOOP /? end if no more messages in the group ?/ END IF JUMP TO READ.NEXT END.LOOP: * $STATUSD = 2247 if the Queue has wrong index type IF $STATUSD = 2247 THEN AUDIT 'WRONG TYPE OF INDEX FOR MATCH' ELSE AUDIT ' Messages in the group: ' WITH %COUNT END IF CLOSE QUEUE %QN

Supporting Java messages with the RFH2 keyword

The RFH2=(image | BUFFER) option of the MQGET and MQPUT statements support Java messages and the MQRFH2 header. The following example includes SOUL statements using the RFH2 keyword.

WRITE IMAGE MQRFH2 ON BUFFER POSITION 1 * the RFH2 header is now in the buffer MQPUT DATA1 ON %QNAME GSTATUS %GSTAT - LOGICAL_ORDER RFH2 BUFFER - GROUPID %GRP DESCRIPTOR MQMD * The following MQGET reads the RFH2 header into the * image called MQRFH2, and the data into the %variable * called %TEXT MQGET %TEXT FROM %QNAME NO_WAIT - DESCRIPTOR MQMD - RFH2 MQRFH2

See MQGET statement and MQPUT statement for syntax layout and more details.

Updating the Version 2 message descriptor (MQMD V2)

The image definition for the message descriptor, which you can retrieve using the DESCRIPTOR option, is updated to include the new fields in MQMD Version 2. The following sample image can be specified as target of the WebSphere MQ MQGET DESCRIPTOR option. It matches the layout of the WebSphere MQ MQMD data structure that is described in the WebSphere MQ Application Programming Reference.

IMAGE MQMD * THIS IS THE VERSION 2 MQMD STRUCID IS STRING LEN 4 * TYPE OF STRUCTURE VERSION IS BINARY LEN 4 * VERSION NUMBER OF THE STRUCTURE REPORT IS BINARY LEN 4 * OPTIONS FOR REPORT MESSAGES MSGTYPE IS BINARY LEN 4 * THE TYPE OF MESSAGE * (1=REQUEST, 2=REPLY, 4=REPORT, 8=DATAGRAM) EXPIRY IS BINARY LEN 4 * MESSAGE LIFETIME FEEDBACK IS BINARY LEN 4 * FEEDBACK CODE ENCODING IS BINARY LEN 4 * DATA ENCODING CODECHARSETID IS BINARY LEN 4 * CODED CHARACTER SET IDENTIFIER FORMAT IS STRING LEN 8 * FORMAT NAME PRIORITY IS BINARY LEN 4 * MESSAGE PRIORITY PERSISTENCE IS BINARY LEN 4 * MESSAGE PERSISTENCE MSGID IS STRING LEN 24 * MESSAGE IDENTIFIER CORRELID IS STRING LEN 24 * CORRELATION IDENTIFIER BACKOUTCOUNT IS BINARY LEN 4 * BACKOUT COUNTER REPLYTOQ IS STRING LEN 48 * NAME OF REPLY QUEUE FOR REQUESTS REPLYTOMGR IS STRING LEN 48 * NAME OF REPLY QUEUE MANAGER FOR REQUESTS USERIDENTIFIER IS STRING LEN 12 * USER IDENTIFIER ACCOUNTINGTOKEN IS STRING LEN 32 * ACCOUNTING TOKEN APPLIDENTITYDATA IS STRING LEN 32 * APPL DATA RELATING TO IDENTITY PUTAPPLTYPE IS BINARY LEN 4 * TYPE OF APPLICATION THAT PUT THE MSG PUTAPPLNAME IS STRING LEN 28 * ID OF APPLICATION THAT PUT THE MESSAGE PUTDATE IS STRING LEN 8 * DATE WHEN MESSAGE WAS PUT PUTTIME IS STRING LEN 8 * TIME WHEN MESSAGE WAS PUT APPLORIGINDATA IS STRING LEN 4 * APPLICATION DATA RELATING TO ORIGIN GROUPID IS STRING LEN 24 * GROUP ID MSGSEQNO IS BINARY LEN 4 * MESSAGE SEQUENCE NUMBER WITHIN GROUP OFFSET IS BINARY LEN 4 * OFFSET OF SEGMENT WITHIN MESSAGE MSGFLAGS IS BINARY LEN 4 * MESSAGE FLAGS ORGLEN IS BINARY LEN 4 * ORIGINAL LENGTH END IMAGE

MQRFH2 image format

You can use the following image when there are no variable length fields.

IMAGE MQRFH2 * THIS IS THE RFH2 HEADER FOR JAVA STRUCID IS STRING LEN 4 * TYPE OF STRUCTURE'RFH ' VERSION IS BINARY LEN 4 * VERSION NUMBER OF THE STRUCTURE - 2 LENGTH IS BINARY LEN 4 * LENGTH OF THE STRUCTURE (36) ENCODING IS BINARY LEN 4 * THE TYPE OF ENCODING CHARSET IS BINARY LEN 4 * CODEDCHARSETID OF DATA FORMAT IS STRING LEN 8 * FORMAT OF DATA FOLLOWING RFH2 FLAGS IS BINARY LEN 4 * FLAGS - SET TO 0 NAMEVALUECCSID IS BINARY LEN 4 * 1208, 1200, 13488, OR 17584 * CODEDCHARSETID OF VARIABLE PART END IMAGE

MQMD version compatibility

MQ messages written with the MQ Message Descriptor (MQMD) Version 2 cannot be read by Model 204 V6R1.0, or earlier, Onlines. However, MQ messages written with MQMD Version 1 can by read by Model 204 V6R3.0 Onlines.

The MQMD is a part of the MQ message. It is referred to as the message header. An Online that uses Version 1 of the MQMD header, such as MQ/204 V6R1.0, cannot read messages from a Version 2 MQMD header, due to additional fields in the message header. However, an Online that uses Version 2 of the MQMD header, such as MQ/204 V6R3.0, can read messages from a Version 1 MQMD header, because the Version 2 header new fields provide default values.

See also