Asynchronous message consumption and callback routines

Asynchronous message consumption, which is available in Version 7 or later of IBM® MQ, uses the MQCB and MQCTL MQI calls. If you use these functions in a CICS application program, CICS carries out some aspects of the processing, so when you code your application you must use the information given here in addition to using the IBM MQ programming documentation.

To use IBM MQ asynchronous message consumption, you can register programs known as callback routines for multiple message destinations, including queues and topics. When a suitable message is sent to the destination, it is passed to the callback routine. You can also set up event handlers to be notified of conditions such as a queue manager quiescing.

When you register a CICS command level application program as a callback routine, CICS obtains the messages passed by IBM MQ and links to the callback routine using EXEC CICS LINK. CICS passes the message data to the callback routine in a set of containers on a channel.

A program that you use as a callback routine must meet the following requirements:
  • Your callback routine can be in any programming language supported by CICS, but note that using Java for a callback routine causes excessive TCB switching between the Java and non-Java environments, which affects performance.
  • Compile and link-edit your callback routine with the RENT option and the options AMODE(31), RMODE(ANY).
  • Code your callback routine to threadsafe standards, and define it to CICS with the attributes CONCURRENCY(THREADSAFE) and API(CICSAPI), to optimize the amount of TCB switching. Using API(OPENAPI) would affect performance because excessive TCB switching occurs if storage protection is active for a callback routine.

    A program defined with CONCURRENCY(REQUIRED) and API(CICSAPI) enables a program coded to threadsafe standards to run from the start of the program on an open TCB. An L8 open TCB is used regardless of the execution key.

  • Define your callback routine as a local program, not as remote, or dynamic. Remote and dynamic programs are not supported as callback routines because the data structures that CICS passes in the containers include pointers to local storage in a region. An attempt to register a callback routine that is defined as remote fails with the reason code MQRC_MODULE_NOT_FOUND.

CICS containers for callback routines

The containers that CICS passes to callback routines use a channel named MQ_ASYNC_CONSUME. The name of the channel, and the names of the containers, are all 16 characters long, so the names of the containers given here are padded with blanks. The containers are as follows:
Table 1. Message data containers passed to callback routines
Container name Content
MsgDesc MQMD2 - Message descriptor version 2
GetMsgOpts MQGMO - Get Message Options
Buffer The message. Options specified in MQGMO, such as truncation and conversion, have the same effects on the message as they do with an MQGET call.
Context MQCBC - Callback Context version 2
The IBM MQ product documentation describes the MQMD, MQGMO, and MQCBC data structures. See IBM MQ product documentation.

When your callback routine retrieves data from the message data containers, use GET CONTAINER SET commands rather than GET CONTAINER INTO commands, to allow for future changes in the size of the data structures. Code the FLENGTH keyword and test for its value being zero, to check for empty containers. For example, for event invocations of callback routines, the MsgDesc, GetMsgOpts, and Buffer containers are empty.

Handling sync points, abends, and quiesce in callback routines

To ensure that your callback routine interacts correctly with the CICS®-MQ adapter, ensure that the following requirements are met:

  1. Use the EXEC CICS SYNCPOINT and EXEC CICS SYNCPOINT ROLLBACK commands only in message consumer callback routines when they are started for a message. Do not use these commands in event handlers, or when callback routines are called to register, deregister, start, or stop.
  2. If you use the EXEC CICS ABEND command in a callback routine, the MQCTL command fails with reason code MQRC_CALLBACK_ERROR(2452), because the abend is handled and control is returned to the caller. An abend in one callback routine stops invocation of all callback routines being managed by the CICS task that issued the MQCTL request.
  3. In an event handler callback routine, issue an MQCTL STOP command when the queue manager or connection is quiescing, to enable the CICS-MQ interface to quiesce successfully. If you do not issue this command, the CICS-MQ interface cannot quiesce because of the active event handler, and the CICS-MQ interface must be force closed.
  4. When you use MQCB to register a callback routine:
    1. In the CallBackDesc (MQCBD) parameter, do not set MQCBDO_FAIL_IF_QUIESCING in the Options field. CICS needs to issue MQCB commands as part of its processing to stop new work arriving.
    2. In the GetMsgOpts (MQGMO) parameter, do set MQGMO_FAIL_IF_QUIESCING in the Options field, to ensure proper quiesce of the callback routine. If you do not set these quiesce options correctly, the CICS-MQ interface cannot quiesce because of the active event handler, and the CICS-MQ interface must be force closed.
    3. In the CallBackDesc (MQCBD) parameter, if you want to use the CallbackArea field to pass an area of storage to the callback routine, set it to the address of storage obtained using EXEC CICS GETMAIN rather than the program's dynamic storage. The callback routine accesses this storage using the CallbackArea field in the Callback context structure MQCBC. Also, when the program ends, do not free the storage or any further storage areas anchored off it, but let CICS freemain the storage at the end of the task. This allows the storage to be available if CICS invokes the callback routine to deregister during end of task processing.
  5. When you use MQCTL to control invocations of callback routines, in the ControlOpts (MQCTLO) parameter, if you want to use the ConnectionArea field to pass an area of storage to be shared by all callback routines, set it to the address of storage obtained using EXEC CICS GETMAIN rather than the program's dynamic storage. Callback routines access this storage using the ConnectionArea field in the Callback context structure MQCBC. Also, when the program ends, do not free the storage or any further storage areas anchored off it, but let CICS freemain the storage at the end of the task. This allows the storage to be available if CICS invokes the callback routines to deregister during end of task processing.