Foreword
CICS and WebSphere MQ is pretty simple, all it can start is TRANSACTIONS and CKTI acts the same way and that's that. COMMIT and BACKOUT is done under control of CICS as syncpoint coordinator using EXEC CICS SYNCPOINT or EXEC CICS SYNCPOINT ROLLBACK
You can write your own CKTI add-on and place it on a new transaction and let CKTI start it, and then let your add-on do the LINK PROGRAM(). based on the message content and/or PROCESS USERDATA-field.
Depending on your program design, if the wrapper do the MQGET, the message is gone when the program will retrieve it... There a some analysis to be done.
I've seen some of this kind of wrapper applications, but they face some problems:
1. how about running more programs simultaneously ?
2. how about performance measurements, regarding SLA ?
3. how about accounting ?
4. what about security ?
and the list is much longer.
Well, what I've seen (and it works fairly good) is a single wrapper program (single transaction), which just uses the MQTM (trigger message) to decide which program to start (One application program per queue), and based on USERDATA, start the program, and pass the MQTM as commarea. Then it's completely up to the application program to do all the MQ-stuff.
My Intention of this page is NOT to write all the things you have to consider, it's meant as a supplement to the manuals.
Let's start to set the CICS triggering up
I can't emphasize the value of understanding how triggering works. I've spend many hours reading the pages over and over again. It's just a couple of pages with many use full information.
We need an initiation queue that receives the trigger message(MQTM), in my example it's called ATGLQUEUE.
As long as the initiation queue is not open for input (see below), you will not be able to get a trigger.
This is the ATGLQUEUE display Queue name . . . . . . . . . ATGLQUEUE Description . . . . . . . . : Output use count . . . . . : 0 Input use count . . . . . . : 0 |
You will have to tell CKTI to read from ATGLQUEUE, this could be done in CSQCPARM on the CICS or using CICS transaction: CKQC
If you use CSQCPARM, it's located inside INITPARM of the CICS, and CSQCPARM is specified like this:
INITPARM=(CSQCPARM=’SN=CSQ1,TN=001,IQ=ATGLQUEUE’) |
If you use CKQC, you'll see a interface like this:
Connection CKTI Task ------------------ +--------------------+------------------------------------- CKQCM0 CIC ! Select an action. !itial panel ! ! Select menu bar it ! 1 1. Start... !press Enter. ! 2. Stop... ! ! 3. Display ! ! ! +--- +--------------------------------------------------+ ! F1 ! Start Task Initiator ! +--- ! ! ! Type Initiation Queue Name. Then press Enter. ! ! ! ! Initiation Queue Name (IQ) . . . . . . . . . . . ! ! ATGLQUEUE ! ! ! +--------------------------------------------------+ IBM WebSphere MQ for z/ ! F1=Help F12=Cancel ! +--------------------------------------------------+ (C) Copyright IBM Corporation 1993, 2003. All rights reserved. F1=Help F3=Exit |
You can see when CKTI is correctly setup... by displaying ATGLQUEUE, and look on Input use count . . . . . . : which should show 1.
I would recommend following reading:
Application programming guide, chapter: Conditions for a trigger event
I started the CKTI instance for ATGLQUEUE. Now the open input count is 1, but it is still not triggering.
Queue name . . . . . . . . . ATGLQUEUE Description . . . . . . . . : Put enabled . . . . . . . . : Y Y=Yes,N=No Get enabled . . . . . . . . : Y Y=Yes,N=No Usage . . . . . . . . . . . : N N=Normal,X=XmitQ Storage class . . . . . . . : DEFAULT Creation method . . . . . . : PREDEFINED Output use count . . . . . : 0 Input use count . . . . . . : 1 Current queue depth . . . . : 0 |
You can use CKQC to investigate how it's working:
CKQCM4 Display CKTI panel Read CKTI status information. Then press F12 to cancel. CKTI 1 to 1 of 1 Task Num Task Status Thread Status Num of APIs Last API ---------- ------------- --------------- ------------ ---------- 0000042 Normal Msg Wait 56 MQGET Initiation Queue Name: ATGLQUEUE F1=Help F7=Backward F8=Forward F12=Cancel Enter=Refresh |
Is there any data in data queue ?
The reason for asking is: when using TRIGTYPE(FIRST), you will have a trigger when qdepth goes from 0->1 and the queue is NOT open for INPUT. General rule.
MQ will generate an additional trigger when you put a mug, and qdepth > 1, if the queue is NOT open for INPUT and TRIGINT has expired or when the queue is closed.
You can force MQ to generate another trigger, by changing the TRIGGER-attributes in MQ-EXPLORE or using MQSC.
When you know MQ have generated a trigger msg, take a look on the log of the CKTI-CICS. There might be an failure here.... which result in some message here...
An example could be that the transaction was undefined or that the userid who is running the trigger-monitor(CKTI) have insufficient access to the transaction
examples of the log to come:
Example of the status display:
CKQCM2 Display Connection panel Read connection information. Then press F12 to cancel. CICS Applid = TESTCICS Connection Status = Connected QMgr name= CSQ1 Trace Num = 001 Tracing = On API Exit = On Initiation Queue Name = ATGLQUEUE --------------------------------- STATISTICS --------------------------------- Number of in-flight tasks = 1 Total API calls = 7626 Number of running CKTI = 1 APIs and flows analysis Syncpoint Recovery ---------------------------------------- ------------------- --------------- Run OK 7575 MQINQ 0 Tasks 51 Indoubt 0 Futile 0 MQSET 0 Backout 0 UnResol 0 MQOPEN 201 ------ Flows ------ Commit 1780 Commit 0 MQCLOSE 200 Calls 9629 S-Phase 1780 Backout 0 MQGET 1885 SyncComp 9407 2-Phase 0 GETWAIT 1885 SuspReqd 0 ------------- Task Use ------------- MQPUT 5340 Msg Wait 222 Initial 8 Started 8 Busy 0 MQPUT1 0 Switched 9628 F1=Help F12=Cancel Enter=Refresh |
Troubleshooting
When I we see something like example 1 below, it's a piece of cake. My user (MRMQ) is not authorized to start CKTI (and that's ok in this case). This start should be done with the CICS userid. If it's the right user that is trying to start CKTI, we are going to have a chat with the security administration. Just show him the log.
>DFHXS1111 07/27/04 16:35:37 CICSA CKTI Security violation by user MRMQ >for resource CKTI in class TCICSTRN. SAF codes are >(X'00000004',X'00000000'). ESM codes are (X'00000004',X'00000000'). >DFHAC2003 07/27/04 16:35:37 CICSA Security violation has been detected term >id = ????, trans id = CKTI, userid =MRMQ. |
Next example from the real world. Once again I'm using CKQC to see what is happening, and it shows status=Starting. This status tells me to look in the CICS-log, and see if ATGLQUEUE is opend for input. Normally the status should be Running.
CKQCM4 Display CKTI panel Read CKTI status information. Then press F12 to cancel. CKTI 1 to 1 of 1 Task Num Task Status Thread Status Num of APIs Last API ---------- ------------- --------------- ------------ ---------- Starting Initiation Queue Name: ATGLQUEUE |
A typical MQ triggered CICS program
Retrieve MQTM (CICS Commarea) Getmain Storage MQOPEN "LOOP" MQGET (on 20 sec MQ Wait Interval) "DO the job-code" MQPUT1 (to ReplyToQueue/ReplyToQmgr) SYNCPOINT or ‘Rollback’ “ENDLOOP” MQCLOSE CICS Return |
Comments on using CICS triggering
-
Design always your application so it don't crate a loop when an error occurs eg. you do a SYNCPOINT Backout and terminate your program. As soon the queue is closed and the trigger conditions are meet a new trigger is fired.. This is an advanced loop. You might take advance of BackoutCount, which tells you how many times there have been a backout
-
Use MQTM to obtain which queue caused the trigger event.
-
Always issue error messages to a file or log for ease troubleshooting, you can't have to much information in case of an problem. Things will go wrong, and it's always under high stress to solve the problems. I've spend hours troubleshooting applications getting RC=2085, 2035 etc., that didn't tell anything about bad reason codes.
At least: Function, Queue, Reasoncode. Like "MQPUT1 CSQ1.MY.QUEUE RC=2035". In this case there should also be a log entry in systemlog, and CSQ1MSTR from SAF, telling which profile that caused the security violation. But if we're dealing with 2085 no messages are shown from WebSphere MQ, you have to do it all in your application.
Make a standardized procedure/function to issue the failure reporting, like you do in DB2. ;o) -
When using CKTI your transaction will run using the authority of CKTI, this means that you should think of which user should start CKTI. You could have more CKTI running serving different INIT-queues under different users.
-
Remember that RC=2033 (MQRC_NQ_MSG_AVAILABLE) is a good rc, this means you don't have to issue a log-entry for this. It will only mesh up your log.
-
Always do MQGET under MQGMO_SYNCPOINT, so you don't loose messages due to a program failure. (There might be reasons for issuing MQGET with MQGMO_NO_SYNCPOINT, but that's up to you to decide).