Messaging patterns in CICS enable communication between transactions and tasks, allowing applications to share data, coordinate work, and integrate with external systems. The primary messaging mechanisms in CICS are Temporary Storage Queues (TSQ) and Transient Data Queues (TDQ). Understanding when and how to use these patterns is essential for building efficient, maintainable CICS applications.
CICS messaging patterns provide mechanisms for inter-transaction and inter-task communication within CICS applications. These patterns enable applications to pass data between transactions, store temporary information, trigger asynchronous processing, and interface with external systems. The two primary messaging mechanisms are Temporary Storage Queues (TSQ) and Transient Data Queues (TDQ), each with distinct characteristics and use cases.
Key messaging patterns in CICS:
Imagine you have two mailboxes: one is like a bulletin board where you can pin messages and read them as many times as you want (TSQ), and another is like a letter slot where once someone reads the letter, it disappears (TDQ). Sometimes you want to keep messages around to read later (TSQ), and sometimes you want messages to be read once and then go away (TDQ). CICS messaging patterns help programs talk to each other using these special mailboxes!
Temporary Storage Queues (TSQ) are used to store data temporarily for sharing between tasks within a CICS region. TSQs support both random and sequential access, allowing flexible data retrieval. Data in TSQs persists until explicitly deleted or until the CICS region is restarted.
| Characteristic | Description |
|---|---|
| Access Method | Both random and sequential access supported |
| Data Persistence | Data remains until explicitly deleted or region restart |
| Storage Location | Main storage or auxiliary storage (based on queue name and configuration) |
| Queue Naming | Dynamically defined at runtime |
| Read Behavior | Data can be read multiple times |
| Queue Creation | Created automatically on first write |
Data is written to a TSQ using the WRITEQ TS command. The queue is created automatically if it doesn't exist. You can write data to main storage (faster) or auxiliary storage (more capacity) depending on the queue name prefix.
12345678910111213141516171819202122232425262728293031323334353637IDENTIFICATION DIVISION. PROGRAM-ID. WRITE-TSQ-EXAMPLE. AUTHOR. MAINFRAME MASTER. DATA DIVISION. WORKING-STORAGE SECTION. 01 QUEUE-NAME PIC X(8) VALUE 'USERDATA'. 01 DATA-AREA. 05 CUSTOMER-ID PIC X(10). 05 CUSTOMER-NAME PIC X(30). 05 CUSTOMER-BALANCE PIC S9(9)V99 COMP-3. 01 DATA-LENGTH PIC S9(4) COMP VALUE 44. 01 RESPONSE-CODE PIC S9(8) COMP. PROCEDURE DIVISION. MAIN-LOGIC. *> Prepare data MOVE '1234567890' TO CUSTOMER-ID MOVE 'JOHN DOE' TO CUSTOMER-NAME MOVE 1250.50 TO CUSTOMER-BALANCE *> Write data to TSQ EXEC CICS WRITEQ TS QUEUE(QUEUE-NAME) FROM(DATA-AREA) LENGTH(DATA-LENGTH) RESP(RESPONSE-CODE) END-EXEC *> Check for errors IF RESPONSE-CODE NOT = DFHRESP(NORMAL) DISPLAY 'Error writing to TSQ: ' RESPONSE-CODE ELSE DISPLAY 'Data written to TSQ successfully' END-IF GOBACK.
In this example:
Sequential reads from a TSQ read items in order. Each read advances the current position pointer. The queue maintains its position until reset or the queue is deleted.
123456789101112131415161718192021222324252627282930313233343536373839404142IDENTIFICATION DIVISION. PROGRAM-ID. READ-TSQ-SEQUENTIAL. AUTHOR. MAINFRAME MASTER. DATA DIVISION. WORKING-STORAGE SECTION. 01 QUEUE-NAME PIC X(8) VALUE 'USERDATA'. 01 DATA-AREA. 05 CUSTOMER-ID PIC X(10). 05 CUSTOMER-NAME PIC X(30). 05 CUSTOMER-BALANCE PIC S9(9)V99 COMP-3. 01 DATA-LENGTH PIC S9(4) COMP VALUE 44. 01 RESPONSE-CODE PIC S9(8) COMP. 01 END-OF-QUEUE PIC X VALUE 'N'. 88 END-OF-QUEUE-FLAG VALUE 'Y'. PROCEDURE DIVISION. MAIN-LOGIC. *> Reset queue position to start EXEC CICS READQ TS QUEUE(QUEUE-NAME) INTO(DATA-AREA) LENGTH(DATA-LENGTH) RESP(RESPONSE-CODE) END-EXEC *> Check response EVALUATE RESPONSE-CODE WHEN DFHRESP(NORMAL) DISPLAY 'Customer ID: ' CUSTOMER-ID DISPLAY 'Customer Name: ' CUSTOMER-NAME DISPLAY 'Balance: ' CUSTOMER-BALANCE WHEN DFHRESP(QIDERR) DISPLAY 'Queue not found' WHEN DFHRESP(ITEMERR) SET END-OF-QUEUE-FLAG TO TRUE DISPLAY 'End of queue reached' WHEN OTHER DISPLAY 'Error reading TSQ: ' RESPONSE-CODE END-EVALUATE GOBACK.
Random access allows reading specific items by item number. Item numbers start at 1. This is useful when you need to access specific data without reading through all previous items.
123456789101112131415161718192021222324252627282930313233343536IDENTIFICATION DIVISION. PROGRAM-ID. READ-TSQ-RANDOM. AUTHOR. MAINFRAME MASTER. DATA DIVISION. WORKING-STORAGE SECTION. 01 QUEUE-NAME PIC X(8) VALUE 'USERDATA'. 01 DATA-AREA. 05 CUSTOMER-ID PIC X(10). 05 CUSTOMER-NAME PIC X(30). 05 CUSTOMER-BALANCE PIC S9(9)V99 COMP-3. 01 DATA-LENGTH PIC S9(4) COMP VALUE 44. 01 ITEM-NUMBER PIC S9(8) COMP VALUE 3. 01 RESPONSE-CODE PIC S9(8) COMP. PROCEDURE DIVISION. MAIN-LOGIC. *> Read specific item by number EXEC CICS READQ TS QUEUE(QUEUE-NAME) INTO(DATA-AREA) LENGTH(DATA-LENGTH) ITEM(ITEM-NUMBER) RESP(RESPONSE-CODE) END-EXEC *> Check response IF RESPONSE-CODE = DFHRESP(NORMAL) DISPLAY 'Item ' ITEM-NUMBER ' read successfully' DISPLAY 'Customer: ' CUSTOMER-NAME ELSE DISPLAY 'Error reading item ' ITEM-NUMBER DISPLAY 'Response code: ' RESPONSE-CODE END-IF GOBACK.
Key points about random access:
TSQs should be deleted when no longer needed to free storage resources. TSQs in main storage are automatically deleted when the CICS region restarts, but it's good practice to delete them explicitly.
123456789101112131415161718192021222324252627IDENTIFICATION DIVISION. PROGRAM-ID. DELETE-TSQ-EXAMPLE. AUTHOR. MAINFRAME MASTER. DATA DIVISION. WORKING-STORAGE SECTION. 01 QUEUE-NAME PIC X(8) VALUE 'USERDATA'. 01 RESPONSE-CODE PIC S9(8) COMP. PROCEDURE DIVISION. MAIN-LOGIC. *> Delete the TSQ EXEC CICS DELETEQ TS QUEUE(QUEUE-NAME) RESP(RESPONSE-CODE) END-EXEC *> Check response IF RESPONSE-CODE = DFHRESP(NORMAL) DISPLAY 'TSQ deleted successfully' ELSE IF RESPONSE-CODE = DFHRESP(QIDERR) DISPLAY 'Queue not found (may already be deleted)' ELSE DISPLAY 'Error deleting TSQ: ' RESPONSE-CODE END-IF GOBACK.
TSQs can be stored in main storage or auxiliary storage. The storage location is typically determined by the queue name prefix:
12345678910111213*> Main storage TSQ (default, faster) EXEC CICS WRITEQ TS QUEUE('USERDATA') *> Stored in main storage FROM(DATA-AREA) LENGTH(DATA-LENGTH) END-EXEC *> Auxiliary storage TSQ (survives restart) EXEC CICS WRITEQ TS QUEUE('EXTRA') *> Prefix indicates auxiliary storage FROM(DATA-AREA) LENGTH(DATA-LENGTH) END-EXEC
Transient Data Queues (TDQ) are designed for sequential data processing and communication with external systems. TDQs support only sequential FIFO (First In, First Out) access, and data is automatically deleted after being read once. TDQs must be predefined in the Destination Control Table (DCT).
| Characteristic | Description |
|---|---|
| Access Method | Sequential FIFO only (First In, First Out) |
| Data Persistence | Data deleted automatically after being read once |
| Storage Location | Disk (defined in Destination Control Table) |
| Queue Naming | Must be predefined in DCT (Destination Control Table) |
| Read Behavior | Read-destructive (data removed after read) |
| Automatic Task Initiation | Can automatically start transactions when trigger level reached |
Data is written to a TDQ using the WRITEQ TD command. The queue must be predefined in the DCT. TDQs are typically used for logging, interfacing with batch jobs, or sending data to printers.
12345678910111213141516171819202122232425262728293031323334353637IDENTIFICATION DIVISION. PROGRAM-ID. WRITE-TDQ-EXAMPLE. AUTHOR. MAINFRAME MASTER. DATA DIVISION. WORKING-STORAGE SECTION. 01 QUEUE-NAME PIC X(4) VALUE 'LOGQ'. 01 LOG-RECORD PIC X(80). 01 DATA-LENGTH PIC S9(4) COMP VALUE 80. 01 RESPONSE-CODE PIC S9(8) COMP. PROCEDURE DIVISION. MAIN-LOGIC. *> Prepare log record STRING 'ERROR: Customer validation failed for ID: 1234567890' DELIMITED BY SIZE INTO LOG-RECORD END-STRING *> Write to TDQ EXEC CICS WRITEQ TD QUEUE(QUEUE-NAME) FROM(LOG-RECORD) LENGTH(DATA-LENGTH) RESP(RESPONSE-CODE) END-EXEC *> Check response IF RESPONSE-CODE = DFHRESP(NORMAL) DISPLAY 'Log record written successfully' ELSE IF RESPONSE-CODE = DFHRESP(QIDERR) DISPLAY 'TDQ not found - check DCT definition' ELSE DISPLAY 'Error writing to TDQ: ' RESPONSE-CODE END-IF GOBACK.
Reading from a TDQ is sequential only. Each read removes the record from the queue (read-destructive). Once a record is read, it cannot be read again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748IDENTIFICATION DIVISION. PROGRAM-ID. READ-TDQ-EXAMPLE. AUTHOR. MAINFRAME MASTER. DATA DIVISION. WORKING-STORAGE SECTION. 01 QUEUE-NAME PIC X(4) VALUE 'LOGQ'. 01 LOG-RECORD PIC X(80). 01 DATA-LENGTH PIC S9(4) COMP VALUE 80. 01 RESPONSE-CODE PIC S9(8) COMP. 01 END-OF-QUEUE PIC X VALUE 'N'. 88 END-OF-QUEUE-FLAG VALUE 'Y'. PROCEDURE DIVISION. MAIN-LOGIC. PERFORM UNTIL END-OF-QUEUE-FLAG *> Read from TDQ EXEC CICS READQ TD QUEUE(QUEUE-NAME) INTO(LOG-RECORD) LENGTH(DATA-LENGTH) RESP(RESPONSE-CODE) END-EXEC *> Check response EVALUATE RESPONSE-CODE WHEN DFHRESP(NORMAL) DISPLAY 'Log record: ' LOG-RECORD *> Process the log record PERFORM PROCESS-LOG-RECORD WHEN DFHRESP(QIDERR) DISPLAY 'Queue not found' SET END-OF-QUEUE-FLAG TO TRUE WHEN DFHRESP(ENDDATA) DISPLAY 'End of queue reached' SET END-OF-QUEUE-FLAG TO TRUE WHEN OTHER DISPLAY 'Error reading TDQ: ' RESPONSE-CODE SET END-OF-QUEUE-FLAG TO TRUE END-EVALUATE END-PERFORM GOBACK. PROCESS-LOG-RECORD. *> Process the log record *> (e.g., write to file, send alert, etc.) DISPLAY 'Processing: ' LOG-RECORD.
Automatic Task Initiation (ATI) is a powerful TDQ feature that automatically starts a CICS transaction when the queue reaches a specified number of records (trigger level). This enables event-driven processing patterns.
ATI is configured in the Destination Control Table (DCT) by setting the TRIGLEV parameter. When the number of records in the TDQ reaches the trigger level, CICS automatically initiates the specified transaction.
12345678* Example DCT definition with ATI DEFINE TDQUEUE(LOGQ) GROUP(APPL) DESCRIPTION('Log Queue with ATI') DESTID(LOGQ) TRANSID(LOGP) *> Transaction to start TRIGLEV(10) *> Start transaction when 10 records DESTTYPE(XOPROG) *> External program destination STATUS(ENABLED)
In this example:
12345678910111213141516171819202122232425262728293031323334353637383940*> Program that processes log queue when triggered by ATI IDENTIFICATION DIVISION. PROGRAM-ID. LOGPROC. AUTHOR. MAINFRAME MASTER. DATA DIVISION. WORKING-STORAGE SECTION. 01 QUEUE-NAME PIC X(4) VALUE 'LOGQ'. 01 LOG-RECORD PIC X(80). 01 DATA-LENGTH PIC S9(4) COMP VALUE 80. 01 RECORD-COUNT PIC S9(8) COMP VALUE 0. 01 RESPONSE-CODE PIC S9(8) COMP. PROCEDURE DIVISION. MAIN-LOGIC. DISPLAY 'Log processing transaction started by ATI' *> Process all records in queue PERFORM UNTIL RESPONSE-CODE = DFHRESP(ENDDATA) EXEC CICS READQ TD QUEUE(QUEUE-NAME) INTO(LOG-RECORD) LENGTH(DATA-LENGTH) RESP(RESPONSE-CODE) END-EXEC IF RESPONSE-CODE = DFHRESP(NORMAL) ADD 1 TO RECORD-COUNT DISPLAY 'Processing record ' RECORD-COUNT ': ' LOG-RECORD *> Process the log record PERFORM PROCESS-LOG-RECORD END-IF END-PERFORM DISPLAY 'Processed ' RECORD-COUNT ' log records' GOBACK. PROCESS-LOG-RECORD. *> Process log record (e.g., write to file, database, etc.) DISPLAY 'Log: ' LOG-RECORD.
| Feature | TSQ | TDQ |
|---|---|---|
| Access Method | Random and sequential | Sequential FIFO only |
| Data Persistence | Until explicitly deleted or region restart | Deleted after read (read-destructive) |
| Storage Location | Main storage or auxiliary storage | Disk (DCT defined) |
| Queue Definition | Dynamic at runtime | Predefined in DCT |
| Multiple Reads | Yes, data can be read multiple times | No, data deleted after first read |
| Automatic Task Initiation | No | Yes (via TRIGLEV in DCT) |
| Use Case | Inter-task communication, temporary storage | External system integration, logging, batch processing |
Use TSQ to pass data between transactions. Transaction A writes data to a TSQ, and Transaction B reads it.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354*> Transaction A: Write customer data IDENTIFICATION DIVISION. PROGRAM-ID. TXNA. DATA DIVISION. WORKING-STORAGE SECTION. 01 QUEUE-NAME PIC X(8) VALUE 'CUSTDATA'. 01 CUSTOMER-DATA PIC X(100). 01 RESPONSE-CODE PIC S9(8) COMP. PROCEDURE DIVISION. *> Prepare customer data MOVE 'Customer information...' TO CUSTOMER-DATA *> Write to TSQ EXEC CICS WRITEQ TS QUEUE(QUEUE-NAME) FROM(CUSTOMER-DATA) LENGTH(100) RESP(RESPONSE-CODE) END-EXEC *> Start transaction B EXEC CICS START TRANSID('TXNB') END-EXEC GOBACK. *> Transaction B: Read customer data IDENTIFICATION DIVISION. PROGRAM-ID. TXNB. DATA DIVISION. WORKING-STORAGE SECTION. 01 QUEUE-NAME PIC X(8) VALUE 'CUSTDATA'. 01 CUSTOMER-DATA PIC X(100). 01 RESPONSE-CODE PIC S9(8) COMP. PROCEDURE DIVISION. *> Read from TSQ EXEC CICS READQ TS QUEUE(QUEUE-NAME) INTO(CUSTOMER-DATA) LENGTH(100) RESP(RESPONSE-CODE) END-EXEC IF RESPONSE-CODE = DFHRESP(NORMAL) *> Process customer data DISPLAY 'Processing: ' CUSTOMER-DATA END-IF *> Clean up EXEC CICS DELETEQ TS QUEUE(QUEUE-NAME) END-EXEC GOBACK.
Use TDQ with ATI to automatically process data when it arrives. This pattern is useful for asynchronous processing and workload distribution.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657*> Producer: Write work items to TDQ IDENTIFICATION DIVISION. PROGRAM-ID. WORK-PRODUCER. DATA DIVISION. WORKING-STORAGE SECTION. 01 QUEUE-NAME PIC X(4) VALUE 'WORKQ'. 01 WORK-ITEM PIC X(80). 01 RESPONSE-CODE PIC S9(8) COMP. PROCEDURE DIVISION. *> Generate work items PERFORM VARYING I FROM 1 BY 1 UNTIL I > 100 STRING 'Work item ' I DELIMITED BY SIZE INTO WORK-ITEM END-STRING *> Write to TDQ (ATI will start processor when trigger reached) EXEC CICS WRITEQ TD QUEUE(QUEUE-NAME) FROM(WORK-ITEM) LENGTH(80) RESP(RESPONSE-CODE) END-EXEC END-PERFORM GOBACK. *> Consumer: Automatically started by ATI when trigger level reached IDENTIFICATION DIVISION. PROGRAM-ID. WORK-PROCESSOR. DATA DIVISION. WORKING-STORAGE SECTION. 01 QUEUE-NAME PIC X(4) VALUE 'WORKQ'. 01 WORK-ITEM PIC X(80). 01 RESPONSE-CODE PIC S9(8) COMP. PROCEDURE DIVISION. *> Process all available work items PERFORM UNTIL RESPONSE-CODE = DFHRESP(ENDDATA) EXEC CICS READQ TD QUEUE(QUEUE-NAME) INTO(WORK-ITEM) LENGTH(80) RESP(RESPONSE-CODE) END-EXEC IF RESPONSE-CODE = DFHRESP(NORMAL) *> Process work item DISPLAY 'Processing: ' WORK-ITEM PERFORM PROCESS-WORK-ITEM END-IF END-PERFORM GOBACK. PROCESS-WORK-ITEM. *> Process the work item DISPLAY 'Work item processed: ' WORK-ITEM.
Use TDQ for logging and audit trails. Log records are written to TDQ and processed by a separate transaction (possibly via ATI) that writes them to permanent storage.
1234567891011121314151617181920212223242526272829303132333435*> Logging utility IDENTIFICATION DIVISION. PROGRAM-ID. LOG-UTILITY. DATA DIVISION. WORKING-STORAGE SECTION. 01 LOG-QUEUE PIC X(4) VALUE 'AUDIT'. 01 LOG-RECORD. 05 LOG-TIMESTAMP PIC X(26). 05 LOG-TRANSACTION PIC X(4). 05 LOG-USERID PIC X(8). 05 LOG-MESSAGE PIC X(42). 01 LOG-LENGTH PIC S9(4) COMP VALUE 80. 01 RESPONSE-CODE PIC S9(8) COMP. PROCEDURE DIVISION USING LOG-MESSAGE. *> Get current timestamp EXEC CICS ASKTIME ABSTIME(LOG-TIMESTAMP) END-EXEC *> Get transaction ID EXEC CICS ASSIGN TRANSID(LOG-TRANSACTION) END-EXEC *> Get user ID EXEC CICS ASSIGN USERID(LOG-USERID) END-EXEC *> Write log record to TDQ EXEC CICS WRITEQ TD QUEUE(LOG-QUEUE) FROM(LOG-RECORD) LENGTH(LOG-LENGTH) RESP(RESPONSE-CODE) END-EXEC GOBACK.
Always delete TSQs when they are no longer needed to prevent resource exhaustion. This is especially important for TSQs in main storage.
12345*> Always clean up TSQs EXEC CICS DELETEQ TS QUEUE(QUEUE-NAME) RESP(RESPONSE-CODE) END-EXEC
Use descriptive queue names that indicate their purpose. For TSQs, consider including user ID or transaction ID in the name for uniqueness.
12345678910111213*> Good: Descriptive queue name 01 QUEUE-NAME PIC X(8) VALUE 'CUSTDATA'. *> Better: Include user ID for uniqueness 01 USER-ID PIC X(8). 01 QUEUE-NAME PIC X(16). PROCEDURE DIVISION. EXEC CICS ASSIGN USERID(USER-ID) END-EXEC STRING 'CUST' USER-ID DELIMITED BY SIZE INTO QUEUE-NAME END-STRING
Always check response codes and handle errors appropriately. Common errors include QIDERR (queue not found) and ITEMERR (item not found for random reads).
1234567891011121314151617181920212223EXEC CICS READQ TS QUEUE(QUEUE-NAME) INTO(DATA-AREA) LENGTH(DATA-LENGTH) RESP(RESPONSE-CODE) END-EXEC EVALUATE RESPONSE-CODE WHEN DFHRESP(NORMAL) *> Success - process data WHEN DFHRESP(QIDERR) *> Queue not found DISPLAY 'Queue does not exist' WHEN DFHRESP(ITEMERR) *> Item not found (for random reads) DISPLAY 'Item does not exist' WHEN DFHRESP(ENDDATA) *> End of queue (for sequential reads) DISPLAY 'End of queue reached' WHEN OTHER *> Other error DISPLAY 'Unexpected error: ' RESPONSE-CODE END-EVALUATE
Choose main storage for frequently accessed, small queues. Use auxiliary storage for larger queues or data that needs to survive region restarts.
Leverage ATI with TDQs for event-driven processing. This enables asynchronous processing patterns and better workload distribution.
Monitor queue usage to identify potential issues. Use CICS monitoring tools to track queue sizes, read/write rates, and error conditions.
CICS messaging patterns provide essential mechanisms for inter-transaction communication and data sharing. Key points to remember:
Understanding these messaging patterns enables you to build efficient, maintainable CICS applications with proper inter-transaction communication and data sharing.
1. What is the primary difference between TSQ and TDQ access methods?
2. What happens to data in a TDQ after it is read?
3. How are TSQ queue names defined?
4. What is Automatic Task Initiation (ATI) used for?
5. Where are TSQs typically stored?
Learn about MRO and how messaging patterns work across multiple CICS regions
Understanding ISC and how to communicate between different CICS systems
Learn about integrating IBM MQ with CICS for asynchronous messaging
Understanding session management and how messaging patterns support user sessions