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:
- Specify and start the transaction that will process messages arriving on the specified MQ queue.
- Automatically start the transaction when the CICS-MQ connection is established.
- Automatically stop the transaction when the CICS-MQ connection is terminated.
- Define the user ID to be associated with the MQ monitoring task.
- Define the user ID that will be used for starting the CICS application when no other suitable user ID is supplied.
- 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:
- Retrieve messages from an MQ queue (named REQQUE in this scenario).
- Perform some application logic.
- (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
- The MQMONITOR is automatically started when the CICS-MQ connection is established.
- 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
- 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.
- 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).
- 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.
- 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.
- 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.
- 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.
- 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: