Search

Getting started with CICS Triggering

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 



F1=Help  F7=Backward  F8=Forward  F12=Cancel  Enter=Refresh

 


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).

 

Login Form