CICS - Group home

Using MQMONITORs to simplify the administration of CICS-MQ trigger monitors and MQ message consumers

  

To simplify administration of applications that access IBM MQ, CICS TS V5.4 introduces the MQMONITOR resource which provides easier control over CICS-MQ trigger monitor or MQ message consumer tasks.

Function overview

Capabilities of an MQMONITOR:

    1. Specify and start the transaction that will process messages arriving on the specified MQ queue.
    2. Automatically start the transaction when the CICS-MQ connection is established.
    3. Automatically stop the transaction when the CICS-MQ connection is terminated.
    4. Define the user ID to be associated with the MQ monitoring task.
    5. Define the user ID that will be used for starting the CICS application when no other suitable user ID is supplied.
    6. Define data that will be passed to the started transaction by using the MONDATA attribute.

There is no restriction other than practical limits such as MXT or storage to constrain the number of MQMONITOR tasks running in a CICS region.

Why use MQMONITORs

Maximum benefit is obtained when you use MQMONITORs to manage instances of the CICS-MQ trigger monitor transaction, the CICS-MQ Bridge, and user-written MQ message consuming applications.

Managing instances of the IBM-supplied CICS-MQ trigger monitor transaction CKTI

Prior to CICS TS V5.4 there were a number of issues with the administration of the CKTI transaction:

  • Only one instance of the CKTI transaction is automatically started when the region is started or when the connection to MQ is re-established. All other instances have to be manually started using one of the methods documented in the IBM CICS TS Knowledge Centre.
  • Should CKTI transactions need to be restarted after the MQ connection is re-established, only the default CKTI is started automatically. All the others need to be started manually and they then use the authority of the currently signed-on user, which is a security exposure. A restart of the CICS region may be required in order to start the trigger monitor transactions with the correct security definitions.

Using an MQMONITOR to control CKTI simplifies management:

  • There is no natural limit to the number of MQMONITORs that can be installed in a CICS region and there can be multiple instances of CKTI running without any manual intervention. Of course, it is subject to practical limits as mentioned earlier.
  • You can have multiple MQMONITORs accessing a single MQ queue, including initiation queues. In order to do this, the queue must be defined as open,shared.
  • Defining the MQMONITOR with attribute AUTOSTART(YES) tells CICS to automatically start the CKTI transaction when the connection is established. This transaction is stopped when CICS disconnects from the MQ Queue Manager.
  • You can use the MONUSERID attribute to define a user ID that will be associated with the MQMONITOR transaction.
  • Likewise, you can use the USERID attribute to define a user ID for the triggered CICS application when no other suitable user ID is available.

Therefore, as you can see, the MQMONITOR provides a powerful method of administering MQ consumers such as the CICS-MQ trigger monitor.

Let’s explore further, with a simple, typical scenario, how this new CICS capability can save your effort in administrating a typical MQ message consumer.

Scenario: Using an MQMONITOR to administer an MQ message consumer

Many CICS customers have MQ message consumers running in CICS regions which may not use MQ triggering. An MQ message consumer (named MYTRAN in this scenario) essentially performs the following tasks:

  1. Retrieve messages from an MQ queue (named REQQUE in this scenario).
  2. Perform some application logic.
  3. (Optional) Respond with a reply message, which is sent to a reply queue. (Not covered in this scenario)

In this case, MQ triggering will not be used, which means that the MQ message consumer gets the messages directly from application input queues and performs the necessary function. In this scenario, the program should be monitoring REQQUE when the CICS-MQ connection is established and use MQGET with the WAIT option to retrieve messages from REQQUE as they arrive.

Step 1. Setting up MQMONITOR for administering MQ message consumer MYTRAN

Detailed instructions are given in the CICS TS Knowledge Center topic Defining and installing MQMONITOR resources.

For this scenario, the following attributes must be specified for the MQMONITOR:

Attribute Value Note
AUTOSTART YES Enables MQ message consumer MYTRAN to start automatically when the connection to the MQ queue manager is established.

MONUSERID USER1 Sets the user ID to be associated with MQ message consumer MYTRAN.
QNAME REQQUE
STATUS ENABLED
TRANSACTION MYTRAN

Result

  1. The MQMONITOR is automatically started when the CICS-MQ connection is established.
  2. When the MQMONITOR is started, the EXEC CICS START command starts the MQ message consumer transaction MYTRAN with FROM data which contains the values in MONDATA prepended with <mqmonitor_nameUSERID>.

Step 2. Programming MQ message consumer MYTRAN program to support MQMONITOR

The MQ message consumer program should perform the following steps in the sequence as indicated below:

  • Check that the transaction has been started with data by using an EXEC CICS ASSIGN STARTCODE command.

    EXEC CICS ASSIGN
              STARTCODE(startcode_space)
              RESP(resp_value_space)
    END-EXEC
    

  • Retrieve the FROM data that was passed when your transaction was started into a structure, by issuing an EXEC CICS RETRIEVE command.

     EXEC CICS RETRIEVE INTO(mondata_space)
               RESP(resp_value_space)
     END-EXEC
     

    Use the mqmonitor_name that is passed in bytes 2 through 9 of this data for the following steps.

  • Issue EXEC CICS SET MQMONITOR(mqmonitor_name) STARTED to set the state of the MQ monitor as specified in the retrieved data to started. As you perform this step, you may want to ensure that the MQMONITOR exists before attempting to start it.

    EXEC CICS INQUIRE MQMONITOR(mqmonitor_name)
              QNAME(qname)
              RESP(resp_value_space)
    END-EXEC
    
    IF resp_value_space = DFHRESP(NORMAL)
       EXEC CICS SET MQMONITOR(mqmonitor_name)
                     STARTED
                     RESP(resp_value_space)
       END-EXEC
    ELSE
       GO TO A-MAIN-END
    END-IF
    

  • Open the MQ queue.
  • Get messages on the input queue REQQUE.
  • Do the required application logic.
  • When ending the program for any reason, issue EXEC CICS SET MQMONITOR(mqmonitor_name) STOPPED to set the state of the MQ monitor to stopped.

      EXEC CICS SET MQMONITOR(mqmonitor_name)
                    STOPPED
                    RESP(resp_value_space)
      END-EXEC
      

  • Return to CICS.

See the appendix at the end of this article for complete source code that performs the above steps.

Migrating to MQMONITORs from PLTPI processing

Prior to the introduction of the MQMONITOR resource in CICS Transaction Server V5.4, customers used a number of methods for connecting to IBM MQ and starting CICS-MQ CKTI Trigger Monitor transactions. The most common method was to use a PLTPI program to start the connection to IBM MQ and then start the required instance of CKTI and the CICS MQ Bridge. Others used sequential terminals. But both had the same issues when it came to restarting the transactions after recycling IBM MQ or the CICS MQCONN – it all had to be done manually with security implications.

The introduction of this resource together with the existing MQCONN resource and SIT parameter MQCONN=YES removes the need to have a PLTPI program to connect to IBM MQ and start instances of the CKTI transaction.

Troubleshooting MQMONITORs

  1. A common issue seems to be that users are still using old methodologies and trying to use MQMONITORs at the same time, leading to confusion and unpredictable results.
  2. If the MQCONN definition has a value in the INITQNAME parameter, this results in an MQMONITOR with the name of DFHMQINI being dynamically installed with attributes AUTOSTART, ENABLED and transaction CKTI. If a PLTPI program starts an instance of CKTI using the same MQ queue name, the dynamically installed MQMONITOR may fail to start. The solution is to either stop using a PLTI program (recommended) or remove the MQ queue name from the INITQNAME parameter of the MQCONN definition (which is not recommended).
  3. Multiple attempts are made to start the MQMONITOR during CICS start up.

    This is because the task and program associated with the MQMONITOR have terminated for some reason after the initial attempt to start the MQMONITOR. Every time the WLMHealth percentage is incremented the CICS MQ Alert Manager transaction, CKAM, is notified and it attempts to start all MQMONITORs that are eligible to be started. The user needs to investigate why the transaction associated with the MQMONITOR has terminated.

  4. The MQMONITOR is reported as stopped immediately after a start request.

    Before CICS reports an MQMONITOR as started, it checks to see if the task number associated with the MQMONITOR is running and, if so, whether it is the same transaction ID as specified in the TRANSACTION attribute of the MQMONITOR? If both are true, the MQMONITOR is considered to be started.
    A common issue is that the program associated with the transaction ID has decided that it must terminate. This needs to be investigated and corrected.

  5. The CICS MQ Bridge has been configured as an MQMONITOR and the MQMONITOR stops when invalid data is specified in the MONDATA attribute.

    This is the same behavior as when the CICS MQ Bridge is being started using the command line or sequential terminal. The issue is not with the MQMONITOR resource, but with the invalid parameter. Investigate and correct the cause of the problem.

  6. Some users do not like the default attributes of the dynamically created DFHMQINI resource. APAR PH19015 enables the user to define their own DFHMQINI resource and override the AUTOSTART, STATUS, MONUSERID and USERID attributes.
  7. Before the WLMHEALTH percentage reaches 100%, a second or even a third instance of the transaction associated with the MQMONITOR could be started by the CICS-MQ Alert Manager (CKAM) when it is notified of a change in the WLMHEALTH percentage. User-written MQMONITOR transactions need to be aware that the MQMONITOR could already be in a STARTED state and respond accordingly. CICS APAR PH25261 addresses this issue for the CICS-MQ Trigger Monitor and CICS-MQ Bridge transactions.

Notes:

  • The state of the MQMONITOR is directly dependent on the logic of the program processing the messages on the MQ queue. If this program terminates, the MQMONITOR is considered to be stopped.
  • The program that is used to process incoming messages must adhere to the guidelines detailed in this Knowledge Center topic; otherwise, the MQMONITOR MONSTATUS value is unpredictable.

Appendix: Maintenance applied since CICS TS V5.4

  • APAR PH17093

    This APAR removes START surrogate security userid checking during the installation of an MQMONITOR resource. It also removes surrogate userid checking when the EXEC CICS START request has been issued by program DFHMQMNS.

  • APAR PH19015

    This APAR gives the user the ability to override the default attributes of MQMONITOR resource DFHMQINI by creating their own definition in the same group as the MQCONN resource.

  • APAR PH22316

    This APAR introduces toleration of temporary coupling facility errors for the CICS-MQ Trigger Monitor and the CICS-MQ Bridge transactions.

  • APAR PH25261

    This APAR takes into consideration that a duplicate instance of the CKTI or CKBR transactions could be created during CICS initialization due to a delay in the original transaction being started.

Appendix: Code example for a typical MQ message consumer

CBL NODYNAM,OBJECT,RENT,APOST
      *                                                               *
      * ------------------------------------------------------------- *
       IDENTIFICATION DIVISION.
      * ------------------------------------------------------------- *
       PROGRAM-ID. MQGETTER.
      *REMARKS                                                        *
      *****************************************************************
      *                                                               *
      *  Module Name           : MQGETTER                             *
      *                                                               *
      *  Environment           : CICS, COBOL, MQ                      *
      *                                                               *
      *                                                               *
      *****************************************************************
      *                                                               *
      *                       Program  Logic                          *
      *                       --------------                          *
      *                                                               *
      *   Assign start code                                           *
      *   If started with data then retrieve the data                 *
      *   INQUIRE on the MQMONITOR to get the QNAME                   *
      *   Set the MQMONITOR started                                   *
      *   Open the MQ queue                                           *
      *   Compute the MQ get message options                          *
      *   Loop getting all messages on the input queue and do the     *
      *   required application logic                                  *
      *   Set the MQMONITOR stopped                                   *
      *   Return to CICS                                              *
      *                                                               *
      *****************************************************************
       ENVIRONMENT DIVISION.
      * ------------------------------------------------------------- *
       DATA DIVISION.
      * ------------------------------------------------------------- *
       WORKING-STORAGE SECTION.
      * ------------------------------------------------------------- *
       01  W00-FIELDS.
           03  FILLER                 PIC X(50) VALUE
           '**** Working storage for MQGETTER starts here ****'.
           03  W00-STARTCODE          PIC XX    VALUE SPACES.
           03  W00-QNAME              PIC X(48) VALUE SPACES.
           03  W00-RETURN-CODE        PIC S9(4) BINARY VALUE ZERO.
           03  W00-RESP               PIC S9(9) BINARY VALUE ZERO.
           03  W00-MESSAGE            PIC X(80) VALUE SPACES.
           03  W00-MSGLENGTH          PIC S9(9) BINARY VALUE 32767.
           03  W00-DATALENGTH         PIC S9(9) BINARY VALUE 0.
           03  W00-ERROR-MESSAGE      PIC X(10) VALUE SPACES.
           03  W00-MSGBUFFER.
              05  W00-MSGBUFFER-ARRAY PIC X(1) OCCURS 32767 TIMES.
           03  W00-MONDATA.
               05  FILLER             PIC X.
               05  W00-MQMONITOR      PIC X(8).
               05  W00-USERID         PIC X(8).
               05  FILLER             PIC X.
           03  W00-WAIT-INTERVAL      PIC S9(09) BINARY VALUE 30000.
      *
      *    W03 - API fields
      *
           03  W03-HCONN              PIC S9(9) BINARY VALUE 0.
           03  W03-HOBJ               PIC S9(9) BINARY VALUE 0.
           03  W03-OPENOPTIONS        PIC S9(9) BINARY.
           03  W03-COMPCODE           PIC S9(9) BINARY.
           03  W03-COMPCODE-CHAR      PIC X(9) VALUE SPACES.
           03  W03-REASON             PIC S9(9) BINARY.
           03  W03-REASON-CHAR        PIC X(9) VALUE SPACES.
      *
      *    API control blocks
      *
       01  MQM-OBJECT-DESCRIPTOR.
           COPY CMQODV.
       01  MQM-MESSAGE-DESCRIPTOR.
           COPY CMQMDV.
       01  MQM-GET-MESSAGE-OPTIONS.
           COPY CMQGMOV.
       01  MQTM-TRIGGER-MESSAGE.
           COPY CMQTMV.
      *
      *    MQV contains constants (for filling in the control blocks)
      *    and return codes (for testing the result of a call)
      *
       01  MQM-CONSTANTS.
           COPY CMQV SUPPRESS.
      *
      * ------------------------------------------------------------- *
       LINKAGE SECTION.
      * ------------------------------------------------------------- *
           EJECT
      * ------------------------------------------------------------- *
       PROCEDURE DIVISION.
      * ------------------------------------------------------------- *
      * ------------------------------------------------------------- *
       A-MAIN SECTION.
      * ------------------------------------------------------------- *
      *
           EXEC CICS HANDLE ABEND LABEL(A-ABEND) END-EXEC
      *
           EXEC CICS ASSIGN
                     STARTCODE(W00-STARTCODE)
                     RESP(W00-RESP)
           END-EXEC

           IF W00-STARTCODE NOT EQUAL 'SD'
              MOVE 'NOT STARTED WITH DATA' TO W00-MESSAGE
              PERFORM DISPLAY-MESSAGE
              GO TO A-MAIN-END
           END-IF

           EXEC CICS RETRIEVE INTO(W00-MONDATA)
                              RESP(W00-RESP)
           END-EXEC

           EXEC CICS INQUIRE MQMONITOR(W00-MQMONITOR)
                             QNAME(W00-QNAME)
                             RESP(W00-RESP)
           END-EXEC

           IF W00-RESP = DFHRESP(NORMAL)
              EXEC CICS SET MQMONITOR(W00-MQMONITOR)
                            STARTED
                            RESP(W00-RESP)
              END-EXEC
           ELSE
              GO TO A-MAIN-END
           END-IF
      *
           MOVE W00-QNAME          TO MQOD-OBJECTNAME.
           COMPUTE W03-OPENOPTIONS = MQOO-INPUT-SHARED +
                                     MQOO-FAIL-IF-QUIESCING

      *
           CALL 'MQOPEN' USING W03-HCONN
                               MQOD
                               W03-OPENOPTIONS
                               W03-HOBJ
                               W03-COMPCODE
                               W03-REASON
      *
      *    If open failed display error message and exit
      *
           IF (W03-COMPCODE NOT = MQCC-OK) THEN
              MOVE 'MQOPEN'   TO W00-ERROR-MESSAGE
              PERFORM DISPLAY-ERROR-MESSAGE
              GO TO A-MAIN-END
           END-IF
      *
           COMPUTE MQGMO-OPTIONS = MQGMO-WAIT +
                                   MQGMO-ACCEPT-TRUNCATED-MSG +
                                   MQGMO-SYNCPOINT +
                                   MQGMO-FAIL-IF-QUIESCING
      *
      *    Loop getting the messages.
      *
           PERFORM
               UNTIL (W03-COMPCODE NOT = MQCC-OK)
      *
               MOVE W00-WAIT-INTERVAL TO MQGMO-WAITINTERVAL
               MOVE MQMI-NONE         TO MQMD-MSGID
               MOVE MQCI-NONE         TO MQMD-CORRELID

               CALL 'MQGET' USING W03-HCONN
                                  W03-HOBJ
                                  MQMD
                                  MQGMO
                                  W00-MSGLENGTH
                                  W00-MSGBUFFER
                                  W00-DATALENGTH
                                  W03-COMPCODE
                                  W03-REASON

               EXEC CICS SYNCPOINT END-EXEC
      *
               IF W03-COMPCODE  = MQCC-FAILED
                   IF W03-REASON    = MQRC-NO-MSG-AVAILABLE
                      MOVE MQCC-OK       TO W03-COMPCODE
                   ELSE
                      GO TO A-MAIN-END
                   END-IF
               ELSE
      *
      *           Your error logic goes here
      *
               END-IF
           END-PERFORM

           GO TO A-MAIN-END
           .
       A-ABEND.
           EXEC CICS HANDLE ABEND CANCEL END-EXEC
           MOVE 'ABEND DETECTED' TO W00-MESSAGE
           PERFORM DISPLAY-MESSAGE
           .
       A-MAIN-END.
      *
           EXEC CICS SET MQMONITOR(W00-MQMONITOR)
                         STOPPED
                         RESP(W00-RESP)
           END-EXEC
      *
           EXEC CICS RETURN
           END-EXEC
      *
           .
       A-EXIT.
           GOBACK.
           EJECT
      *
      * ------------------------------------------------------------- *
       DISPLAY-ERROR-MESSAGE SECTION.
      * ------------------------------------------------------------- *
      *
           MOVE W03-COMPCODE            TO W03-COMPCODE-CHAR.
           MOVE W03-REASON            TO W03-REASON-CHAR.
      *
           MOVE SPACES                TO W00-MESSAGE.
           STRING '* ', W00-ERROR-MESSAGE,
                  ' * CC : ', W03-COMPCODE-CHAR,
                  ' * RC : ', W03-REASON-CHAR, ' *'
                  DELIMITED BY SIZE INTO W00-MESSAGE.
           PERFORM DISPLAY-MESSAGE.
      *
       DISPLAY-ERROR-MESSAGE-END.
      *
      *    Return to performing function
      *
           EXIT.
      * ------------------------------------------------------------- *
       DISPLAY-MESSAGE SECTION.
      * ------------------------------------------------------------- *
      *
           DISPLAY W00-MESSAGE.
           MOVE SPACES                TO W00-MESSAGE.
      *
       DISPLAY-MESSAGE-END.
      *
      *    Return to performing function
      *
           EXIT.
      *
      * ------------------------------------------------------------- *
      *
      * ------------------------------------------------------------- *
      *                        END OF PROGRAM
      * ------------------------------------------------------------- *

For more information
Take a look in the CICS documentation: