Programming with the MQI in COBOL
Programs talk to MQ through a small set of calls known as the MQI. A COBOL program connects, opens a queue, puts or gets messages, closes and disconnects, checking a completion code and reason code after every call.
The core calls
| Call | Purpose |
|---|---|
| MQCONN | Connect to a queue manager and get a connection handle (not needed in CICS, which connects for you) |
| MQOPEN | Open a queue for input, output or inquiry, returning an object handle |
| MQPUT | Put a message on an open queue |
| MQGET | Get a message, optionally waiting for one to arrive |
| MQPUT1 | Open, put one message and close, in a single call |
| MQCLOSE | Release the object handle |
| MQDISC | Disconnect from the queue manager |
| MQCMIT / MQBACK | Commit or back out a unit of work in batch (in CICS, use CICS SYNCPOINT instead) |
A put in COBOL
MOVE MQOT-Q TO MQOD-OBJECTTYPE
MOVE 'PAYMENTS.IN' TO MQOD-OBJECTNAME
COMPUTE OPEN-OPTIONS = MQOO-OUTPUT + MQOO-FAIL-IF-QUIESCING
CALL 'MQOPEN' USING HCONN MQOD OPEN-OPTIONS
HOBJ COMPCODE REASON
IF COMPCODE NOT = MQCC-OK
PERFORM MQ-ERROR
END-IF
MOVE MQPER-PERSISTENT TO MQMD-PERSISTENCE
COMPUTE MQPMO-OPTIONS = MQPMO-SYNCPOINT
+ MQPMO-NEW-MSG-ID
CALL 'MQPUT' USING HCONN HOBJ MQMD MQPMO
BUFFER-LENGTH PAYMENT-REC
COMPCODE REASONThe structures (MQOD for object descriptor, MQMD, MQPMO for put options, MQGMO for get options) and the constants come from IBM-supplied copybooks such as CMQV, CMQODV, CMQMDV, CMQPMOV and CMQGMOV. Copy them in rather than coding values by hand.
Completion and reason codes
Every call returns a completion code (MQCC-OK 0, MQCC-WARNING 1, MQCC-FAILED 2) and a reason code that says why. These are the ones you will meet most:
| Reason | Name | Usual meaning |
|---|---|---|
| 2033 | MQRC_NO_MSG_AVAILABLE | The queue is empty (normal at the end of a get loop) |
| 2085 | MQRC_UNKNOWN_OBJECT_NAME | The queue name is wrong or not defined on this queue manager |
| 2035 | MQRC_NOT_AUTHORIZED | The user ID lacks access in RACF to the queue or queue manager |
| 2053 | MQRC_Q_FULL | The queue reached MAXDEPTH; the reader is probably down |
| 2059 | MQRC_Q_MGR_NOT_AVAILABLE | The queue manager is not running or not reachable |
| 2009 | MQRC_CONNECTION_BROKEN | The connection was lost during the call |
| 2080 | MQRC_TRUNCATED_MSG_FAILED | The buffer is smaller than the message |
Getting with a wait
A reader usually sets MQGMO-WAIT with a wait interval so it sleeps until a message arrives instead of looping. When the interval expires with nothing on the queue, the get returns reason 2033 and the program can end cleanly or wait again.
Request and reply
For a request/reply exchange the requester sets ReplyToQ in the MQMD. The server copies the request's MsgId into the reply's CorrelId, and the requester gets the reply by correlation ID. This is how a CICS program matches each answer to its question.
A get loop ends with completion code 2 and reason code 2033. Is this an error the program should report, or the normal 'queue is empty' signal? Answer error or normal.
Show a hint
Look up 2033 in the table above.
Show the solution
normal: 2033 (MQRC_NO_MSG_AVAILABLE) means there was nothing to get. Well-written programs treat it as the end of the loop, not as a failure.
Common mistakes
In CICS the unit of work belongs to CICS. Commit with EXEC CICS SYNCPOINT so MQ and DB2 updates commit together.
2033 at the end of a get loop is expected. Check the specific reason code, not just the completion code.
Without MQGMO-SYNCPOINT the message is gone the moment you get it. If the program then abends, the message is lost.
What you will see at work
- Most MQ incidents are diagnosed from the reason code in the program's log or abend message: learn the common ones by heart.
- Many shops wrap the MQI in a standard copybook or subroutine so every program handles errors the same way.
- Reason 2035 almost always ends with a RACF access request, not a code change.
Key terms
Check your understanding.
Take this lesson's quiz and save your progress. Free.