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.

  7. 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 done automatically. All the others need to be done 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 administrate 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 MONDATA prepended with as the FROM data.

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.

    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
                   END-IF
          *
          *       Insert code here
          *
               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
          * ------------------------------------------------------------- *
    

    Join The Discussion

    Your email address will not be published. Required fields are marked *