Every chapter up to this point has focused on batch processing -- programs that run in the background, processing files from beginning to end without human interaction. But the mainframe is not just a batch engine. When a bank teller looks up your...
In This Chapter
- Introduction: Online Transaction Processing on the Mainframe
- 24.1 CICS Overview: Architecture and Concepts
- 24.2 The EXEC CICS...END-EXEC Interface
- 24.3 SEND TEXT and SEND MAP
- 24.4 RECEIVE MAP: Reading User Input
- 24.5 BMS: Basic Mapping Support
- 24.6 File Control: CICS File Operations
- 24.7 Pseudo-Conversational Programming
- 24.8 The EIB: Execute Interface Block
- 24.9 Error Handling: RESP and RESP2
- 24.10 Program Control: LINK and XCTL
- 24.11 Temporary Storage Queues (TSQ) and Transient Data Queues (TDQ)
- 24.12 CICS and DB2: Combining Transaction Processing with Database Access
- 24.13 CICS Application Design Patterns
- 24.14 CICS Abend Handling
- 24.15 Compiling CICS Programs
- 24.13 Complete CICS Customer Inquiry Program
- Summary
- CICS Programming: Key Restrictions and Differences from Batch
- Exercises
Chapter 24: CICS Transaction Processing Fundamentals
IBM Enterprise COBOL
Introduction: Online Transaction Processing on the Mainframe
Every chapter up to this point has focused on batch processing -- programs that run in the background, processing files from beginning to end without human interaction. But the mainframe is not just a batch engine. When a bank teller looks up your account balance, when an airline agent books your flight, when a government clerk processes your benefit claim on a terminal, the mainframe is processing those requests in real time through an online transaction processing system.
On IBM mainframes, that system is CICS -- the Customer Information Control System. CICS has been the dominant online transaction processing (OLTP) monitor on mainframes since its introduction in 1969. Today it processes an estimated 1.2 million transactions per second worldwide, supporting over 30 billion transactions per day. Banks, airlines, insurance companies, retailers, and government agencies all depend on CICS for their interactive mainframe applications.
CICS provides services that batch programs handle for themselves: terminal management (reading input from and writing output to user screens), task management (running thousands of concurrent transactions), program management (loading and dispatching application programs), file management (providing shared access to files and databases), and recovery management (ensuring data integrity when failures occur).
COBOL programs that run under CICS look different from batch programs. They do not have ENVIRONMENT DIVISION file definitions. They do not use READ, WRITE, OPEN, or CLOSE. They do not use DISPLAY or ACCEPT. Instead, they use EXEC CICS commands -- a parallel command-level API that requests CICS services. A CICS COBOL program is, at its core, a COBOL program with EXEC CICS...END-EXEC statements in place of native file I/O and terminal I/O.
This chapter covers the fundamentals of CICS programming with COBOL: the EXEC CICS interface, terminal I/O with SEND and RECEIVE, screen design with BMS (Basic Mapping Support), file operations, the critical pseudo-conversational programming model, EIB fields, error handling, program control, and temporary storage.
24.1 CICS Overview: Architecture and Concepts
How CICS Works
CICS runs as an address space (region) on z/OS. Within that region, multiple transactions execute concurrently, sharing the same memory space. A transaction is initiated when a user types a transaction identifier (a 1-4 character code) on a 3270 terminal and presses Enter. CICS loads the associated program, creates a task, and dispatches the program to process the request.
Key CICS Concepts
| Concept | Description |
|---|---|
| Transaction | A unit of work initiated by a user, identified by a 4-character TRANSID (e.g., INQC for customer inquiry) |
| Task | A running instance of a transaction. Multiple tasks can run the same transaction concurrently. |
| Program | The COBOL program associated with a transaction, defined in the Program Processing Table (PPT) |
| Terminal | A 3270 screen device where the user interacts with CICS |
| EIB | Execute Interface Block, a control block containing information about the current task |
| COMMAREA | Communication Area, a block of data passed between transaction instances (pseudo-conversational) or between programs |
| BMS | Basic Mapping Support, the facility for formatting 3270 screens |
| PCT | Program Control Table, maps transaction IDs to programs |
| PPT | Processing Program Table, defines programs known to CICS |
| FCT | File Control Table, defines files accessible through CICS file control |
CICS vs. Batch: What Changes
| Batch COBOL | CICS COBOL |
|---|---|
| OPEN, READ, WRITE, CLOSE | EXEC CICS READ, WRITE, REWRITE, DELETE |
| DISPLAY, ACCEPT | EXEC CICS SEND, RECEIVE |
| SELECT...ASSIGN | Files defined in FCT |
| STOP RUN | EXEC CICS RETURN |
| SORT, MERGE | Not available (use batch) |
| FILE STATUS | EXEC CICS RESP/RESP2 |
| Report Writer | Not applicable (use BMS maps) |
24.2 The EXEC CICS...END-EXEC Interface
All CICS services are accessed through the EXEC CICS command interface:
EXEC CICS command
option(value)
option(value)
...
END-EXEC
General Syntax Rules
- EXEC CICS begins every CICS command.
- END-EXEC terminates the command. Like EXEC SQL, do not place a period after END-EXEC unless you intend to end a COBOL sentence.
- Options are keyword-value pairs specific to each command.
- Data items referenced in CICS commands do not use a colon prefix (unlike DB2 host variables).
- Literal values in CICS are enclosed in quotes or apostrophes depending on compiler settings.
Common CICS Commands
* Send data to the terminal
EXEC CICS SEND TEXT
FROM(WS-MESSAGE)
LENGTH(WS-MSG-LENGTH)
END-EXEC
* Read a VSAM record
EXEC CICS READ
FILE('CUSTFILE')
INTO(WS-CUSTOMER-RECORD)
RIDFLD(WS-CUSTOMER-KEY)
LENGTH(WS-REC-LENGTH)
END-EXEC
* Return control to CICS
EXEC CICS RETURN
END-EXEC
24.3 SEND TEXT and SEND MAP
SEND TEXT: Simple Terminal Output
The simplest way to send output to a 3270 terminal is SEND TEXT:
WORKING-STORAGE SECTION.
01 WS-MESSAGE PIC X(80).
01 WS-MSG-LENGTH PIC S9(4) COMP VALUE 80.
PROCEDURE DIVISION.
0000-MAIN.
MOVE 'WELCOME TO CUSTOMER INQUIRY SYSTEM'
TO WS-MESSAGE
EXEC CICS SEND TEXT
FROM(WS-MESSAGE)
LENGTH(WS-MSG-LENGTH)
ERASE
FREEKB
END-EXEC
EXEC CICS RETURN
END-EXEC
.
Key options for SEND TEXT:
| Option | Description |
|---|---|
| FROM(data-area) | The data to send to the terminal |
| LENGTH(data-value) | Length of the data |
| ERASE | Clear the screen before writing |
| FREEKB | Unlock the keyboard so the user can type |
| CURSOR(position) | Position the cursor at a specific screen location |
SEND MAP: Formatted Screen Output
For formatted screens (which is what most CICS applications use), the SEND MAP command sends data to the terminal using a predefined screen layout called a BMS map:
EXEC CICS SEND MAP('CUSTMAP')
MAPSET('CUSTSET')
FROM(CUSTMAPO)
ERASE
FREEKB
CURSOR
END-EXEC
Key options for SEND MAP:
| Option | Description |
|---|---|
| MAP(name) | The map name (defined in the BMS mapset) |
| MAPSET(name) | The mapset name (the BMS load module) |
| FROM(data-area) | The symbolic map output structure |
| ERASE | Clear the screen before sending |
| FREEKB | Unlock the keyboard |
| CURSOR | Position the cursor at the field with the cursor attribute set, or at position (0,0) |
| ERASEAUP | Erase all unprotected fields |
| DATAONLY | Send only data fields, not constant text or attributes |
| MAPONLY | Send only the map layout, not data from the program |
24.4 RECEIVE MAP: Reading User Input
The RECEIVE MAP command reads data entered by the user on a BMS-formatted screen:
EXEC CICS RECEIVE MAP('CUSTMAP')
MAPSET('CUSTSET')
INTO(CUSTMAPI)
END-EXEC
After RECEIVE MAP, the symbolic map input structure (CUSTMAPI) contains the data typed by the user in each input field, along with the length of each field and the attention key pressed (AID key).
Processing Received Data
2000-RECEIVE-AND-PROCESS.
EXEC CICS RECEIVE MAP('CUSTMAP')
MAPSET('CUSTSET')
INTO(CUSTMAPI)
RESP(WS-CICS-RESP)
RESP2(WS-CICS-RESP2)
END-EXEC
IF WS-CICS-RESP = DFHRESP(NORMAL)
* Process the data entered by the user
MOVE CUSTIDI TO WS-SEARCH-KEY
IF WS-SEARCH-KEY = SPACES
MOVE 'PLEASE ENTER A CUSTOMER ID'
TO MSGEXTO
PERFORM 3000-SEND-MAP
ELSE
PERFORM 2100-LOOKUP-CUSTOMER
END-IF
ELSE IF WS-CICS-RESP = DFHRESP(MAPFAIL)
* User pressed Enter without typing anything
MOVE 'NO DATA ENTERED'
TO MSGEXTO
PERFORM 3000-SEND-MAP
END-IF
.
24.5 BMS: Basic Mapping Support
BMS is the CICS facility for defining 3270 screen layouts. A BMS map definition is written in assembler macro language (not COBOL) and is assembled into two outputs: a physical map (a load module that CICS uses to format the screen) and a symbolic map (a COBOL copybook that your program uses to populate and read screen fields).
BMS Map Definition
A BMS mapset consists of three macros:
- DFHMSD: Defines the mapset (a collection of maps)
- DFHMDI: Defines an individual map (screen layout)
- DFHMDF: Defines a field on the map
CUSTSET DFHMSD TYPE=&SYSPARM, X
MODE=INOUT, X
LANG=COBOL, X
STORAGE=AUTO, X
CTRL=(FREEKB,FRSET), X
TIOAPFX=YES
*
CUSTMAP DFHMDI SIZE=(24,80), X
LINE=1, X
COLUMN=1
*
* Row 1: Title
DFHMDF POS=(1,25), X
LENGTH=30, X
ATTRB=(ASKIP,BRT), X
INITIAL='CUSTOMER INQUIRY SCREEN'
*
* Row 3: Customer ID label and input field
DFHMDF POS=(3,2), X
LENGTH=12, X
ATTRB=(ASKIP,NORM), X
INITIAL='CUSTOMER ID:'
*
CUSTID DFHMDF POS=(3,15), X
LENGTH=10, X
ATTRB=(UNPROT,NORM,IC), X
INITIAL=' '
DFHMDF POS=(3,26), X
LENGTH=1, X
ATTRB=ASKIP
*
* Row 5: Customer Name (output)
DFHMDF POS=(5,2), X
LENGTH=5, X
ATTRB=(ASKIP,NORM), X
INITIAL='NAME:'
*
CUSTNM DFHMDF POS=(5,8), X
LENGTH=30, X
ATTRB=(ASKIP,NORM)
*
* Row 7: Balance (output)
DFHMDF POS=(7,2), X
LENGTH=8, X
ATTRB=(ASKIP,NORM), X
INITIAL='BALANCE:'
*
CUSTBAL DFHMDF POS=(7,11), X
LENGTH=14, X
ATTRB=(ASKIP,NORM)
*
* Row 22: Message line
MSGEXT DFHMDF POS=(22,2), X
LENGTH=70, X
ATTRB=(ASKIP,BRT)
*
* Row 24: PF Key instructions
DFHMDF POS=(24,2), X
LENGTH=40, X
ATTRB=(ASKIP,NORM), X
INITIAL='PF3=EXIT PF12=CANCEL ENTER=SEARCH'
*
CUSTSET DFHMSD TYPE=FINAL
END
Understanding Attribute Bytes
Every field on a 3270 screen is preceded by an attribute byte that controls its behavior:
| Attribute | Description |
|---|---|
| ASKIP | Auto-skip: cursor skips over this field (used for labels and output) |
| UNPROT | Unprotected: user can type in this field (input field) |
| PROT | Protected: field is visible but user cannot type in it |
| NORM | Normal intensity display |
| BRT | Bright (highlighted) intensity |
| DRK | Dark (invisible) -- used for password fields |
| NUM | Numeric-only input |
| IC | Initial cursor position |
| FSET | Modified data tag set -- field appears changed even if user did not modify it |
The Symbolic Map (COBOL Copybook)
When you assemble the BMS map with TYPE=DSECT, the assembler generates a COBOL copybook containing the symbolic map. This copybook defines two structures: one for input (suffixed with I) and one for output (suffixed with O):
* Generated by BMS assembly (simplified)
01 CUSTMAPI.
05 FILLER PIC X(12).
05 CUSTIDL PIC S9(4) COMP.
05 CUSTIDF PIC X.
05 FILLER REDEFINES CUSTIDF.
10 CUSTIDA PIC X.
05 CUSTIDI PIC X(10).
05 CUSTNML PIC S9(4) COMP.
05 CUSTNMF PIC X.
05 FILLER REDEFINES CUSTNMF.
10 CUSTNMA PIC X.
05 CUSTNMI PIC X(30).
05 CUSTBALL PIC S9(4) COMP.
05 CUSTBALF PIC X.
05 FILLER REDEFINES CUSTBALF.
10 CUSTBALA PIC X.
05 CUSTBALI PIC X(14).
05 MSGEXTL PIC S9(4) COMP.
05 MSGEXTF PIC X.
05 FILLER REDEFINES MSGEXTF.
10 MSGEXTA PIC X.
05 MSGEXTI PIC X(70).
01 CUSTMAPO REDEFINES CUSTMAPI.
05 FILLER PIC X(12).
05 FILLER PIC X(3).
05 CUSTIDO PIC X(10).
05 FILLER PIC X(3).
05 CUSTNMO PIC X(30).
05 FILLER PIC X(3).
05 CUSTBALO PIC X(14).
05 FILLER PIC X(3).
05 MSGEXTO PIC X(70).
For each named field, the symbolic map includes:
| Suffix | Type | Description |
|---|---|---|
| L | PIC S9(4) COMP | Length of data entered by user (input) |
| F | PIC X | Flag/attribute byte |
| A | PIC X (REDEFINES F) | Attribute byte for output modification |
| I | PIC X(n) | Input data (what the user typed) |
| O | PIC X(n) | Output data (what the program sends) |
Populating and Sending a Map
3000-SEND-CUSTOMER-MAP.
* Clear the output map
MOVE LOW-VALUES TO CUSTMAPO
* Populate output fields
MOVE WS-CUST-ID TO CUSTIDO
MOVE WS-CUST-NAME TO CUSTNMO
MOVE WS-CUST-BAL-FMT TO CUSTBALO
* Set a message
MOVE 'CUSTOMER RECORD FOUND'
TO MSGEXTO
* Send the map
EXEC CICS SEND MAP('CUSTMAP')
MAPSET('CUSTSET')
FROM(CUSTMAPO)
ERASE
FREEKB
CURSOR
END-EXEC
.
24.6 File Control: CICS File Operations
CICS provides its own file control commands for reading and writing VSAM files (and DB2 tables through the DB2 attachment facility). These commands replace the native COBOL READ, WRITE, REWRITE, and DELETE verbs.
READ: Random Read
01 WS-CUSTOMER-RECORD.
05 WS-CUST-KEY PIC X(10).
05 WS-CUST-NAME PIC X(30).
05 WS-CUST-BALANCE PIC S9(7)V99 COMP-3.
05 WS-CUST-STATUS PIC X.
01 WS-REC-LENGTH PIC S9(4) COMP.
01 WS-CICS-RESP PIC S9(8) COMP.
01 WS-CICS-RESP2 PIC S9(8) COMP.
2100-READ-CUSTOMER.
MOVE LENGTH OF WS-CUSTOMER-RECORD
TO WS-REC-LENGTH
EXEC CICS READ
FILE('CUSTFILE')
INTO(WS-CUSTOMER-RECORD)
RIDFLD(WS-SEARCH-KEY)
LENGTH(WS-REC-LENGTH)
RESP(WS-CICS-RESP)
RESP2(WS-CICS-RESP2)
END-EXEC
EVALUATE WS-CICS-RESP
WHEN DFHRESP(NORMAL)
SET WS-CUSTOMER-FOUND TO TRUE
WHEN DFHRESP(NOTFND)
SET WS-CUSTOMER-NOT-FOUND TO TRUE
WHEN DFHRESP(DISABLED)
MOVE 'FILE IS DISABLED' TO MSGEXTO
WHEN DFHRESP(NOTOPEN)
MOVE 'FILE IS NOT OPEN' TO MSGEXTO
WHEN OTHER
PERFORM 9100-CICS-ERROR
END-EVALUATE
.
WRITE: Add a New Record
2200-ADD-CUSTOMER.
MOVE WS-NEW-CUST-KEY TO WS-CUST-KEY
MOVE WS-NEW-CUST-NAME TO WS-CUST-NAME
MOVE 0 TO WS-CUST-BALANCE
MOVE 'A' TO WS-CUST-STATUS
MOVE LENGTH OF WS-CUSTOMER-RECORD
TO WS-REC-LENGTH
EXEC CICS WRITE
FILE('CUSTFILE')
FROM(WS-CUSTOMER-RECORD)
RIDFLD(WS-CUST-KEY)
LENGTH(WS-REC-LENGTH)
RESP(WS-CICS-RESP)
END-EXEC
EVALUATE WS-CICS-RESP
WHEN DFHRESP(NORMAL)
MOVE 'CUSTOMER ADDED SUCCESSFULLY'
TO MSGEXTO
WHEN DFHRESP(DUPREC)
MOVE 'CUSTOMER ALREADY EXISTS'
TO MSGEXTO
WHEN OTHER
PERFORM 9100-CICS-ERROR
END-EVALUATE
.
REWRITE: Update an Existing Record
To update a record, you must first READ it with the UPDATE option, then REWRITE it:
2300-UPDATE-CUSTOMER.
* Read with UPDATE to lock the record
EXEC CICS READ
FILE('CUSTFILE')
INTO(WS-CUSTOMER-RECORD)
RIDFLD(WS-SEARCH-KEY)
LENGTH(WS-REC-LENGTH)
UPDATE
RESP(WS-CICS-RESP)
END-EXEC
IF WS-CICS-RESP = DFHRESP(NORMAL)
* Modify the record
ADD WS-TRANS-AMOUNT TO WS-CUST-BALANCE
* Write the updated record back
EXEC CICS REWRITE
FILE('CUSTFILE')
FROM(WS-CUSTOMER-RECORD)
LENGTH(WS-REC-LENGTH)
RESP(WS-CICS-RESP)
END-EXEC
IF WS-CICS-RESP = DFHRESP(NORMAL)
MOVE 'UPDATE SUCCESSFUL' TO MSGEXTO
ELSE
PERFORM 9100-CICS-ERROR
END-IF
ELSE
EVALUATE WS-CICS-RESP
WHEN DFHRESP(NOTFND)
MOVE 'CUSTOMER NOT FOUND' TO MSGEXTO
WHEN OTHER
PERFORM 9100-CICS-ERROR
END-EVALUATE
END-IF
.
DELETE: Remove a Record
2400-DELETE-CUSTOMER.
EXEC CICS DELETE
FILE('CUSTFILE')
RIDFLD(WS-DELETE-KEY)
RESP(WS-CICS-RESP)
END-EXEC
EVALUATE WS-CICS-RESP
WHEN DFHRESP(NORMAL)
MOVE 'CUSTOMER DELETED' TO MSGEXTO
WHEN DFHRESP(NOTFND)
MOVE 'CUSTOMER NOT FOUND' TO MSGEXTO
WHEN OTHER
PERFORM 9100-CICS-ERROR
END-EVALUATE
.
Browse: Sequential Reading (STARTBR/READNEXT/READPREV/ENDBR)
To read records sequentially in CICS (equivalent to a sequential READ loop in batch), you use the browse commands:
2500-BROWSE-CUSTOMERS.
* Start the browse at a specific key
EXEC CICS STARTBR
FILE('CUSTFILE')
RIDFLD(WS-START-KEY)
GTEQ
RESP(WS-CICS-RESP)
END-EXEC
IF WS-CICS-RESP NOT = DFHRESP(NORMAL)
MOVE 'BROWSE START FAILED' TO MSGEXTO
PERFORM 3000-SEND-MAP
EXEC CICS RETURN END-EXEC
END-IF
* Read records sequentially
PERFORM 2510-READ-NEXT
UNTIL WS-BROWSE-DONE
OR WS-BROWSE-COUNT >= 20
* End the browse
EXEC CICS ENDBR
FILE('CUSTFILE')
RESP(WS-CICS-RESP)
END-EXEC
.
2510-READ-NEXT.
EXEC CICS READNEXT
FILE('CUSTFILE')
INTO(WS-CUSTOMER-RECORD)
RIDFLD(WS-BROWSE-KEY)
LENGTH(WS-REC-LENGTH)
RESP(WS-CICS-RESP)
END-EXEC
EVALUATE WS-CICS-RESP
WHEN DFHRESP(NORMAL)
ADD 1 TO WS-BROWSE-COUNT
PERFORM 2520-DISPLAY-RECORD
WHEN DFHRESP(ENDFILE)
SET WS-BROWSE-DONE TO TRUE
WHEN DFHRESP(NOTFND)
SET WS-BROWSE-DONE TO TRUE
WHEN OTHER
SET WS-BROWSE-DONE TO TRUE
PERFORM 9100-CICS-ERROR
END-EVALUATE
.
24.7 Pseudo-Conversational Programming
Pseudo-conversational programming is the most important concept in CICS application design. Understanding it is essential because virtually all CICS applications use this model.
The Problem: Conversational Programming
In a conversational model, a CICS task starts when the user enters a transaction, and the task remains active while the user reads the screen, thinks, and types a response. This means the task holds memory, locks, and other resources for the entire think-time -- which could be seconds, minutes, or hours if the user goes to lunch.
With thousands of concurrent users, conversational programming would require enormous amounts of memory and system resources.
The Solution: Pseudo-Conversational Programming
In the pseudo-conversational model, the task ends after sending the screen to the user. When the user presses Enter or a PF key, CICS starts a new task to process the response. Between the two tasks, no CICS resources are held.
The key mechanism is the RETURN TRANSID command with a COMMAREA (Communication Area):
* End the current task, specifying:
* - TRANSID: which transaction to start when user responds
* - COMMAREA: data to pass to the next task instance
EXEC CICS RETURN
TRANSID('INQC')
COMMAREA(WS-COMMAREA)
LENGTH(WS-COMMAREA-LENGTH)
END-EXEC
The Pseudo-Conversational Lifecycle
User types "INQC" and presses Enter
|
v
CICS starts Task 1 for TRANSID INQC
|
v
Program sends the inquiry screen (SEND MAP)
|
v
Program executes RETURN TRANSID('INQC') COMMAREA(data)
|
v
Task 1 ENDS -- no resources held
|
(User thinks, types customer ID, presses Enter)
|
v
CICS starts Task 2 for TRANSID INQC
|
v
Program checks EIBCALEN (COMMAREA length)
- EIBCALEN = 0: This is the first invocation (Task 1 path)
- EIBCALEN > 0: This is a subsequent invocation (Task 2+ path)
|
v
Program receives the map (RECEIVE MAP)
|
v
Program processes the request (reads file, etc.)
|
v
Program sends results (SEND MAP)
|
v
Program executes RETURN TRANSID('INQC') COMMAREA(data)
|
v
Task 2 ENDS
|
(cycle repeats)
COMMAREA: Passing Data Between Task Instances
The COMMAREA is a block of data that survives between task instances. It is the only way to pass data from one pseudo-conversational instance to the next. When the program receives control, CICS places the COMMAREA from the previous RETURN in the LINKAGE SECTION:
WORKING-STORAGE SECTION.
01 WS-COMMAREA.
05 CA-TRANS-STATE PIC X.
88 CA-FIRST-TIME VALUE '1'.
88 CA-MAP-SENT VALUE '2'.
88 CA-PROCESSING VALUE '3'.
05 CA-CUSTOMER-KEY PIC X(10).
05 CA-LAST-MAP PIC X(8).
05 CA-ERROR-FLAG PIC 9.
01 WS-COMMAREA-LENGTH PIC S9(4) COMP
VALUE LENGTH OF WS-COMMAREA.
LINKAGE SECTION.
01 DFHCOMMAREA PIC X(100).
The EIBCALEN Check
The program determines whether this is its first invocation or a subsequent invocation by checking EIBCALEN -- the length of the incoming COMMAREA:
PROCEDURE DIVISION.
0000-MAIN.
IF EIBCALEN = 0
* First time -- no COMMAREA, send initial screen
PERFORM 1000-FIRST-TIME
ELSE
* Subsequent invocation -- process user input
MOVE DFHCOMMAREA TO WS-COMMAREA
PERFORM 2000-PROCESS-INPUT
END-IF
.
1000-FIRST-TIME.
INITIALIZE WS-COMMAREA
SET CA-MAP-SENT TO TRUE
MOVE SPACES TO MSGEXTO
MOVE 'ENTER CUSTOMER ID AND PRESS ENTER'
TO MSGEXTO
EXEC CICS SEND MAP('CUSTMAP')
MAPSET('CUSTSET')
FROM(CUSTMAPO)
ERASE
FREEKB
CURSOR
END-EXEC
EXEC CICS RETURN
TRANSID('INQC')
COMMAREA(WS-COMMAREA)
LENGTH(WS-COMMAREA-LENGTH)
END-EXEC
.
2000-PROCESS-INPUT.
* Check which key the user pressed
EVALUATE EIBAID
WHEN DFHPF3
EXEC CICS SEND TEXT
FROM(WS-GOODBYE-MSG)
LENGTH(WS-GOODBYE-LEN)
ERASE
END-EXEC
EXEC CICS RETURN END-EXEC
WHEN DFHPF12
PERFORM 1000-FIRST-TIME
WHEN DFHENTER
PERFORM 2100-HANDLE-ENTER
WHEN OTHER
MOVE 'INVALID KEY PRESSED'
TO MSGEXTO
PERFORM 3000-SEND-MAP-DATAONLY
END-EVALUATE
.
24.8 The EIB: Execute Interface Block
The EIB is a CICS-managed control block that is automatically available to every CICS program. It contains information about the current task, terminal, and transaction.
Key EIB Fields
| Field | Type | Description |
|---|---|---|
| EIBTIME | PIC S9(7) COMP-3 | Current time (0HHMMSS format) |
| EIBDATE | PIC S9(7) COMP-3 | Current date (0CYYDDD format, C=century) |
| EIBTRNID | PIC X(4) | Transaction ID of the current task |
| EIBTASKN | PIC S9(7) COMP-3 | Task number |
| EIBTRMID | PIC X(4) | Terminal ID |
| EIBCPOSN | PIC S9(4) COMP | Cursor position on the screen |
| EIBCALEN | PIC S9(4) COMP | Length of the COMMAREA (0 if none) |
| EIBAID | PIC X | Attention identifier (which key was pressed) |
| EIBFN | PIC X(2) | Function code of the last CICS command |
| EIBRCODE | PIC X(6) | Response code of the last CICS command |
| EIBDS | PIC X(8) | Last dataset (file) name referenced |
| EIBREQID | PIC X(8) | Request identifier |
EIBAID: Attention Identifier Constants
The EIBAID field tells you which key the user pressed. CICS provides copybook DFHAID with predefined constants:
WORKING-STORAGE SECTION.
COPY DFHAID.
* DFHAID defines:
* 01 DFHENTER PIC X VALUE X'7D'. Enter key
* 01 DFHPF1 PIC X VALUE X'F1'. PF1
* 01 DFHPF2 PIC X VALUE X'F2'. PF2
* 01 DFHPF3 PIC X VALUE X'F3'. PF3
* 01 DFHPF12 PIC X VALUE X'7C'. PF12
* 01 DFHPA1 PIC X VALUE X'6C'. PA1
* 01 DFHCLEAR PIC X VALUE X'6D'. Clear key
PROCEDURE DIVISION.
2000-PROCESS-INPUT.
EVALUATE EIBAID
WHEN DFHENTER
PERFORM 2100-PROCESS-ENTER
WHEN DFHPF3
PERFORM 9000-EXIT-PROGRAM
WHEN DFHPF5
PERFORM 2200-REFRESH-DATA
WHEN DFHPF7
PERFORM 2300-PAGE-BACKWARD
WHEN DFHPF8
PERFORM 2400-PAGE-FORWARD
WHEN DFHPF12
PERFORM 2500-CANCEL
WHEN DFHCLEAR
PERFORM 9000-EXIT-PROGRAM
WHEN OTHER
MOVE 'INVALID KEY - USE PF3 TO EXIT'
TO MSGEXTO
PERFORM 3000-SEND-MAP-DATAONLY
END-EVALUATE
.
24.9 Error Handling: RESP and RESP2
CICS error handling uses the RESP and RESP2 options on every CICS command. This is the modern recommended approach, replacing the older HANDLE CONDITION mechanism.
Using RESP and RESP2
01 WS-CICS-RESP PIC S9(8) COMP.
01 WS-CICS-RESP2 PIC S9(8) COMP.
2100-READ-CUSTOMER.
EXEC CICS READ
FILE('CUSTFILE')
INTO(WS-CUSTOMER-RECORD)
RIDFLD(WS-SEARCH-KEY)
LENGTH(WS-REC-LENGTH)
RESP(WS-CICS-RESP)
RESP2(WS-CICS-RESP2)
END-EXEC
EVALUATE WS-CICS-RESP
WHEN DFHRESP(NORMAL)
PERFORM 2110-DISPLAY-CUSTOMER
WHEN DFHRESP(NOTFND)
MOVE 'CUSTOMER NOT FOUND'
TO MSGEXTO
PERFORM 3000-SEND-MAP-DATAONLY
WHEN DFHRESP(DISABLED)
MOVE 'FILE IS CURRENTLY DISABLED'
TO MSGEXTO
PERFORM 3000-SEND-MAP-DATAONLY
WHEN DFHRESP(NOTOPEN)
MOVE 'FILE IS NOT OPEN - CONTACT SUPPORT'
TO MSGEXTO
PERFORM 3000-SEND-MAP-DATAONLY
WHEN OTHER
PERFORM 9100-UNEXPECTED-ERROR
END-EVALUATE
.
Common DFHRESP Values
| DFHRESP Value | Description |
|---|---|
| NORMAL | Operation completed successfully |
| NOTFND | Record not found |
| DUPREC | Duplicate record on WRITE |
| DISABLED | File is disabled |
| NOTOPEN | File is not open |
| ENDFILE | End of file during browse |
| INVREQ | Invalid request (logic error) |
| IOERR | I/O error |
| LENGERR | Length error |
| NOSPACE | No space on file for WRITE |
| MAPFAIL | No data received on RECEIVE MAP |
| PGMIDERR | Program not found (LINK/XCTL) |
| ERROR | General error |
The Older HANDLE CONDITION (For Reference)
The HANDLE CONDITION command was the original CICS error handling mechanism. While still supported, it is not recommended for new programs because it creates non-linear control flow similar to GO TO:
* NOT RECOMMENDED for new programs
EXEC CICS HANDLE CONDITION
NOTFND(2200-NOT-FOUND)
DUPREC(2300-DUPLICATE)
ERROR(9100-ERROR)
END-EXEC
* RECOMMENDED: Use RESP/RESP2 instead
Centralized CICS Error Handler
9100-UNEXPECTED-ERROR.
MOVE SPACES TO WS-ERROR-MESSAGE
STRING 'CICS ERROR - RESP: '
WS-CICS-RESP
' RESP2: '
WS-CICS-RESP2
' EIBTRNID: '
EIBTRNID
' EIBFN: '
EIBFN
DELIMITED BY SIZE
INTO WS-ERROR-MESSAGE
END-STRING
* Log the error
EXEC CICS WRITEQ TD
QUEUE('CSMT')
FROM(WS-ERROR-MESSAGE)
LENGTH(LENGTH OF WS-ERROR-MESSAGE)
END-EXEC
* Display error to user
MOVE WS-ERROR-MESSAGE TO MSGEXTO
PERFORM 3000-SEND-MAP-DATAONLY
EXEC CICS RETURN
TRANSID('INQC')
COMMAREA(WS-COMMAREA)
LENGTH(WS-COMMAREA-LENGTH)
END-EXEC
.
24.10 Program Control: LINK and XCTL
CICS provides two commands for transferring control between programs.
LINK: Call and Return
LINK is the CICS equivalent of the COBOL CALL statement. It transfers control to another program and expects that program to return:
* Call a validation subprogram
EXEC CICS LINK
PROGRAM('CUSTVAL')
COMMAREA(WS-VALIDATION-DATA)
LENGTH(WS-VAL-LENGTH)
RESP(WS-CICS-RESP)
END-EXEC
IF WS-CICS-RESP = DFHRESP(NORMAL)
IF WS-VAL-RETURN-CODE = 0
PERFORM 2200-PROCESS-VALID
ELSE
PERFORM 2300-HANDLE-ERRORS
END-IF
ELSE IF WS-CICS-RESP = DFHRESP(PGMIDERR)
MOVE 'VALIDATION PROGRAM NOT FOUND'
TO MSGEXTO
END-IF
XCTL: Transfer Control (No Return)
XCTL transfers control to another program and does not return to the calling program. It is used for navigating between screens in a menu-driven application:
* Transfer to customer update screen
EXEC CICS XCTL
PROGRAM('CUSTUPD')
COMMAREA(WS-NAVIGATION-DATA)
LENGTH(WS-NAV-LENGTH)
RESP(WS-CICS-RESP)
END-EXEC
* If we get here, XCTL failed
IF WS-CICS-RESP = DFHRESP(PGMIDERR)
MOVE 'UPDATE PROGRAM NOT AVAILABLE'
TO MSGEXTO
PERFORM 3000-SEND-MAP-DATAONLY
END-IF
LINK vs. XCTL
| Feature | LINK | XCTL |
|---|---|---|
| Returns to caller | Yes | No |
| Caller's storage | Preserved | Released |
| Analogy | CALL/RETURN | GO TO (program level) |
| Use case | Call a subroutine | Navigate to next screen |
24.11 Temporary Storage Queues (TSQ) and Transient Data Queues (TDQ)
Temporary Storage Queues (TSQ)
TSQs provide a scratch pad for storing data temporarily. They are commonly used for multi-page browse lists, storing data between pseudo-conversational instances (as an alternative to COMMAREA for large data), and passing data between programs.
* Write data to a TSQ
EXEC CICS WRITEQ TS
QUEUE(WS-TSQ-NAME)
FROM(WS-BROWSE-LINE)
LENGTH(WS-LINE-LENGTH)
RESP(WS-CICS-RESP)
END-EXEC
* Read a specific item from a TSQ
EXEC CICS READQ TS
QUEUE(WS-TSQ-NAME)
INTO(WS-BROWSE-LINE)
LENGTH(WS-LINE-LENGTH)
ITEM(WS-ITEM-NUMBER)
RESP(WS-CICS-RESP)
END-EXEC
* Read the number of items in a TSQ
EXEC CICS READQ TS
QUEUE(WS-TSQ-NAME)
INTO(WS-BROWSE-LINE)
LENGTH(WS-LINE-LENGTH)
ITEM(WS-ITEM-NUMBER)
NUMITEMS(WS-TOTAL-ITEMS)
RESP(WS-CICS-RESP)
END-EXEC
* Delete the entire TSQ when done
EXEC CICS DELETEQ TS
QUEUE(WS-TSQ-NAME)
RESP(WS-CICS-RESP)
END-EXEC
TSQ Naming Convention
TSQ names should be unique per terminal session. A common convention includes the terminal ID:
01 WS-TSQ-NAME PIC X(8).
STRING 'BRW' EIBTRMID
DELIMITED BY SIZE
INTO WS-TSQ-NAME
END-STRING
* Result: 'BRWTxx1' where Txx1 is the terminal ID
Transient Data Queues (TDQ)
TDQs are used for logging, audit trails, and trigger-level processing. Unlike TSQs, TDQ records can only be read once (destructive read):
* Write an audit record to a TDQ
EXEC CICS WRITEQ TD
QUEUE('AUDT')
FROM(WS-AUDIT-RECORD)
LENGTH(WS-AUDIT-LENGTH)
RESP(WS-CICS-RESP)
END-EXEC
* Write to CICS system log
EXEC CICS WRITEQ TD
QUEUE('CSMT')
FROM(WS-LOG-MESSAGE)
LENGTH(WS-LOG-LENGTH)
END-EXEC
24.12 CICS and DB2: Combining Transaction Processing with Database Access
Many CICS applications access DB2 databases in addition to (or instead of) VSAM files. A CICS-DB2 program uses both EXEC CICS and EXEC SQL commands within the same COBOL source.
CICS-DB2 Program Structure
IDENTIFICATION DIVISION.
PROGRAM-ID. CUSTDB2.
DATA DIVISION.
WORKING-STORAGE SECTION.
COPY DFHAID.
COPY CUSTSET.
EXEC SQL INCLUDE SQLCA END-EXEC.
EXEC SQL BEGIN DECLARE SECTION END-EXEC.
01 HV-CUST-ID PIC S9(9) COMP.
01 HV-CUST-NAME PIC X(30).
01 HV-CUST-BALANCE PIC S9(7)V99 COMP-3.
EXEC SQL END DECLARE SECTION END-EXEC.
01 WS-COMMAREA.
05 CA-STATE PIC X.
05 CA-CUST-ID PIC S9(9) COMP.
01 WS-CICS-RESP PIC S9(8) COMP.
01 WS-BAL-DISPLAY PIC Z,ZZZ,ZZ9.99-.
LINKAGE SECTION.
01 DFHCOMMAREA PIC X(20).
PROCEDURE DIVISION.
0000-MAIN.
IF EIBCALEN = 0
PERFORM 1000-SEND-INITIAL-MAP
ELSE
MOVE DFHCOMMAREA TO WS-COMMAREA
PERFORM 2000-PROCESS-INPUT
END-IF
.
2100-LOOKUP-DB2.
MOVE CUSTIDI TO HV-CUST-ID
EXEC SQL
SELECT CUST_NAME, CUST_BALANCE
INTO :HV-CUST-NAME, :HV-CUST-BALANCE
FROM CUSTOMER
WHERE CUST_ID = :HV-CUST-ID
END-EXEC
EVALUATE SQLCODE
WHEN 0
MOVE HV-CUST-NAME TO CUSTNMO
MOVE HV-CUST-BALANCE TO WS-BAL-DISPLAY
MOVE WS-BAL-DISPLAY TO CUSTBALO
MOVE 'CUSTOMER FOUND' TO MSGEXTO
WHEN +100
MOVE 'CUSTOMER NOT FOUND IN DB2'
TO MSGEXTO
WHEN OTHER
STRING 'DB2 ERROR: SQLCODE=' SQLCODE
DELIMITED BY SIZE
INTO MSGEXTO
END-STRING
END-EVALUATE
.
Compilation for CICS-DB2 Programs
Programs that use both CICS and DB2 require three preprocessing steps: DB2 precompile, CICS translation, and COBOL compilation. The order matters -- DB2 precompile typically runs first, followed by CICS translation. With the integrated translator in IBM Enterprise COBOL V5+, the compiler can process both EXEC SQL and EXEC CICS commands in a single compilation step using the compiler options CICS and SQL:
//COBOL EXEC PGM=IGYCRCTL,
// PARM='LIB,RENT,CICS,SQL,LIST,MAP'
SYNCPOINT in CICS
In CICS, EXEC SQL COMMIT is not used directly. Instead, CICS provides its own SYNCPOINT command that coordinates commits across multiple resource managers (DB2, VSAM, MQ):
* In CICS, use SYNCPOINT instead of SQL COMMIT
EXEC CICS SYNCPOINT
RESP(WS-CICS-RESP)
END-EXEC
* For rollback in CICS:
EXEC CICS SYNCPOINT ROLLBACK
RESP(WS-CICS-RESP)
END-EXEC
The SYNCPOINT command ensures that both DB2 and VSAM changes are committed atomically -- either both commit or both roll back.
24.13 CICS Application Design Patterns
Multi-Screen Navigation
Most CICS applications consist of multiple screens (maps) that the user navigates between. A common pattern uses a central dispatch program:
* Menu screen dispatches to function screens
2000-PROCESS-MENU.
EXEC CICS RECEIVE MAP('MENUMAP')
MAPSET('MENUSET')
INTO(MENUMAPI)
RESP(WS-CICS-RESP)
END-EXEC
EVALUATE MENUSELI
WHEN '1'
* Customer Inquiry
EXEC CICS XCTL
PROGRAM('CUSTINQ')
COMMAREA(WS-NAV-DATA)
LENGTH(WS-NAV-LENGTH)
END-EXEC
WHEN '2'
* Customer Update
EXEC CICS XCTL
PROGRAM('CUSTUPD')
COMMAREA(WS-NAV-DATA)
LENGTH(WS-NAV-LENGTH)
END-EXEC
WHEN '3'
* Account Inquiry
EXEC CICS XCTL
PROGRAM('ACCTINQ')
COMMAREA(WS-NAV-DATA)
LENGTH(WS-NAV-LENGTH)
END-EXEC
WHEN OTHER
MOVE 'INVALID SELECTION' TO MSGEXTO
PERFORM 3000-SEND-MENU
END-EVALUATE
.
Data Validation in CICS
CICS programs must validate user input before performing any file or database operations. The validation pattern typically checks each input field and accumulates error messages:
2200-VALIDATE-INPUT.
SET WS-INPUT-VALID TO TRUE
* Check customer ID is entered
IF CUSTIDL = 0 OR CUSTIDI = SPACES
MOVE -1 TO CUSTIDL
MOVE 'CUSTOMER ID IS REQUIRED'
TO MSGEXTO
SET WS-INPUT-INVALID TO TRUE
END-IF
* Check customer ID is numeric
IF WS-INPUT-VALID
IF CUSTIDI NOT NUMERIC
MOVE -1 TO CUSTIDL
MOVE 'CUSTOMER ID MUST BE NUMERIC'
TO MSGEXTO
SET WS-INPUT-INVALID TO TRUE
END-IF
END-IF
* If input is invalid, resend the map with cursor
* positioned at the first error field
IF WS-INPUT-INVALID
EXEC CICS SEND MAP('CUSTMAP')
MAPSET('CUSTSET')
FROM(CUSTMAPO)
DATAONLY
FREEKB
CURSOR
END-EXEC
EXEC CICS RETURN
TRANSID('INQC')
COMMAREA(WS-COMMAREA)
LENGTH(WS-COMMAREA-LENGTH)
END-EXEC
END-IF
.
The technique of setting the field's length (L suffix) to -1 before SEND MAP positions the cursor at that field, directing the user's attention to the error.
Handling Concurrent Updates (Optimistic Locking)
In pseudo-conversational applications, the time between displaying a record and updating it can be long (the user's think time). Another user might update the same record during that time. Optimistic locking detects this conflict:
01 WS-COMMAREA.
05 CA-STATE PIC X.
05 CA-CUST-KEY PIC X(10).
05 CA-ORIG-BALANCE PIC S9(7)V99 COMP-3.
05 CA-TIMESTAMP PIC X(26).
* When displaying the record, save the current values
2100-DISPLAY-FOR-UPDATE.
EXEC CICS READ
FILE('CUSTFILE')
INTO(WS-CUSTOMER-RECORD)
RIDFLD(WS-CUST-KEY)
LENGTH(WS-REC-LENGTH)
RESP(WS-CICS-RESP)
END-EXEC
IF WS-CICS-RESP = DFHRESP(NORMAL)
* Save original values in COMMAREA
MOVE WS-CUST-BALANCE TO CA-ORIG-BALANCE
MOVE WS-CUST-TIMESTAMP TO CA-TIMESTAMP
PERFORM 3000-SEND-UPDATE-MAP
END-IF
.
* When updating, verify the record has not changed
2200-APPLY-UPDATE.
EXEC CICS READ
FILE('CUSTFILE')
INTO(WS-CUSTOMER-RECORD)
RIDFLD(CA-CUST-KEY)
LENGTH(WS-REC-LENGTH)
UPDATE
RESP(WS-CICS-RESP)
END-EXEC
IF WS-CICS-RESP = DFHRESP(NORMAL)
* Check if record was modified since we displayed it
IF WS-CUST-TIMESTAMP NOT = CA-TIMESTAMP
MOVE 'RECORD CHANGED BY ANOTHER USER'
TO MSGEXTO
EXEC CICS UNLOCK
FILE('CUSTFILE')
END-EXEC
PERFORM 3000-SEND-MAP-DATAONLY
ELSE
* Safe to update
PERFORM 2210-APPLY-CHANGES
EXEC CICS REWRITE
FILE('CUSTFILE')
FROM(WS-CUSTOMER-RECORD)
LENGTH(WS-REC-LENGTH)
RESP(WS-CICS-RESP)
END-EXEC
MOVE 'UPDATE SUCCESSFUL' TO MSGEXTO
END-IF
END-IF
.
24.14 CICS Abend Handling
CICS provides its own abend mechanism with four-character abend codes. Some abends are issued by CICS itself (system abends), and others can be issued by the application program.
Common CICS Abend Codes
| Abend Code | Description |
|---|---|
| ASRA | Program check (equivalent to S0Cx system abends) |
| AICA | Program is in a runaway loop |
| AEI0 | Program raised an exception |
| AKCP | The program issued an EXEC CICS command that is not valid for the context |
| APCT | Program not found (PCT entry missing) |
| AFCR | File not found (FCT entry missing) |
HANDLE ABEND
The HANDLE ABEND command establishes an abend exit routine. If the program abends, CICS transfers control to the specified paragraph or program instead of terminating:
0000-MAIN.
EXEC CICS HANDLE ABEND
LABEL(9500-ABEND-EXIT)
END-EXEC
* Normal processing
PERFORM 1000-PROCESS
EXEC CICS RETURN END-EXEC
.
9500-ABEND-EXIT.
MOVE 'PROGRAM ABENDED - PLEASE RETRY'
TO MSGEXTO
EXEC CICS SEND MAP('CUSTMAP')
MAPSET('CUSTSET')
FROM(CUSTMAPO)
ERASE
FREEKB
END-EXEC
EXEC CICS RETURN END-EXEC
.
ABEND Command
A CICS program can deliberately abend with a user-specified code:
IF WS-CRITICAL-ERROR
EXEC CICS ABEND
ABCODE('UERR')
CANCEL
END-EXEC
END-IF
The CANCEL option terminates the transaction and releases all resources. Without CANCEL, the abend can be intercepted by a HANDLE ABEND routine.
24.15 Compiling CICS Programs
CICS COBOL programs require a translation step before compilation, similar to the DB2 precompile. The CICS translator processes EXEC CICS commands and replaces them with CALL statements to the CICS runtime.
The Build Process
COBOL Source with EXEC CICS
|
v
CICS TRANSLATOR (DFHECP1$)
- Converts EXEC CICS commands to CALL statements
- Adds DFHEIBLK and DFHCOMMAREA to LINKAGE
|
v
Modified COBOL Source
|
v
COBOL COMPILE (IGYCRCTL)
|
v
LINK-EDIT (IEWL) with CICS stubs
|
v
Load Module (deployed to CICS region)
JCL for CICS Translation, Compile, and Link
//*------------------------------------------------------------
//* STEP 1: CICS TRANSLATION
//*------------------------------------------------------------
//TRN EXEC PGM=DFHECP1$,
// PARM='COBOL3,SP'
//STEPLIB DD DSN=CICSTS.V5R6M0.SDFHLOAD,DISP=SHR
//SYSIN DD DSN=USER.SRCLIB(CUSTINQ),DISP=SHR
//SYSPRINT DD SYSOUT=*
//SYSPUNCH DD DSN=&&CICSOUT,DISP=(NEW,PASS),
// UNIT=SYSDA,SPACE=(800,(500,500))
//*
//*------------------------------------------------------------
//* STEP 2: COBOL COMPILE
//*------------------------------------------------------------
//COB EXEC PGM=IGYCRCTL,
// PARM='LIB,RENT,LIST,MAP,XREF'
//STEPLIB DD DSN=IGY.V6R4M0.SIGYCOMP,DISP=SHR
//SYSIN DD DSN=&&CICSOUT,DISP=(OLD,DELETE)
//SYSLIB DD DSN=USER.COPYLIB,DISP=SHR
// DD DSN=CICSTS.V5R6M0.SDFHCOB,DISP=SHR
// DD DSN=CICSTS.V5R6M0.SDFHMAC,DISP=SHR
//SYSPRINT DD SYSOUT=*
//SYSLIN DD DSN=&&LOADSET,DISP=(NEW,PASS),
// UNIT=SYSDA,SPACE=(800,(500,500))
//SYSUT1 DD UNIT=SYSDA,SPACE=(800,(500,500))
//SYSUT2 DD UNIT=SYSDA,SPACE=(800,(500,500))
//SYSUT3 DD UNIT=SYSDA,SPACE=(800,(500,500))
//SYSUT4 DD UNIT=SYSDA,SPACE=(800,(500,500))
//*
//*------------------------------------------------------------
//* STEP 3: LINK-EDIT
//*------------------------------------------------------------
//LKED EXEC PGM=IEWL,
// PARM='LIST,MAP,RENT,AMODE=31,RMODE=ANY'
//SYSLIB DD DSN=CEE.SCEELKED,DISP=SHR
// DD DSN=CICSTS.V5R6M0.SDFHLOAD,DISP=SHR
//SYSLMOD DD DSN=USER.CICS.LOADLIB(CUSTINQ),DISP=SHR
//SYSLIN DD DSN=&&LOADSET,DISP=(OLD,DELETE)
// DD *
INCLUDE SYSLIB(DFHELII)
NAME CUSTINQ(R)
/*
//SYSPRINT DD SYSOUT=*
Integrated CICS Translator
Modern versions of IBM Enterprise COBOL (V5+) support the integrated CICS translator, which eliminates the separate translation step. The compiler option CICS tells the compiler to process EXEC CICS commands directly:
//COBOL EXEC PGM=IGYCRCTL,
// PARM='LIB,RENT,CICS,LIST,MAP'
//STEPLIB DD DSN=IGY.V6R4M0.SIGYCOMP,DISP=SHR
// DD DSN=CICSTS.V5R6M0.SDFHLOAD,DISP=SHR
24.13 Complete CICS Customer Inquiry Program
The following program demonstrates a complete pseudo-conversational CICS customer inquiry application:
IDENTIFICATION DIVISION.
PROGRAM-ID. CUSTINQ.
*========================================================*
* CICS CUSTOMER INQUIRY PROGRAM *
* TRANSID: INQC *
* MAPSET: CUSTSET / MAP: CUSTMAP *
*========================================================*
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-PROGRAM-ID PIC X(8) VALUE 'CUSTINQ'.
COPY DFHAID.
COPY CUSTSET.
01 WS-COMMAREA.
05 CA-STATE PIC X.
88 CA-INITIAL VALUE SPACES.
88 CA-MAP-SENT VALUE 'M'.
05 CA-CUST-KEY PIC X(10).
01 WS-COMMAREA-LENGTH PIC S9(4) COMP
VALUE LENGTH OF WS-COMMAREA.
01 WS-CUSTOMER-RECORD.
05 WS-CUST-KEY PIC X(10).
05 WS-CUST-NAME PIC X(30).
05 WS-CUST-BALANCE PIC S9(7)V99 COMP-3.
05 WS-CUST-STATUS PIC X.
01 WS-REC-LENGTH PIC S9(4) COMP.
01 WS-CICS-RESP PIC S9(8) COMP.
01 WS-CICS-RESP2 PIC S9(8) COMP.
01 WS-BAL-DISPLAY PIC Z,ZZZ,ZZ9.99-.
01 WS-GOODBYE-MSG PIC X(30)
VALUE 'INQUIRY SESSION ENDED'.
01 WS-GOODBYE-LEN PIC S9(4) COMP VALUE 30.
LINKAGE SECTION.
01 DFHCOMMAREA PIC X(100).
PROCEDURE DIVISION.
0000-MAIN.
IF EIBCALEN = 0
PERFORM 1000-FIRST-TIME
ELSE
MOVE DFHCOMMAREA TO WS-COMMAREA
PERFORM 2000-PROCESS-INPUT
END-IF
.
1000-FIRST-TIME.
INITIALIZE WS-COMMAREA
SET CA-MAP-SENT TO TRUE
MOVE LOW-VALUES TO CUSTMAPO
MOVE 'ENTER CUSTOMER ID AND PRESS ENTER'
TO MSGEXTO
EXEC CICS SEND MAP('CUSTMAP')
MAPSET('CUSTSET')
FROM(CUSTMAPO)
ERASE
FREEKB
CURSOR
END-EXEC
EXEC CICS RETURN
TRANSID('INQC')
COMMAREA(WS-COMMAREA)
LENGTH(WS-COMMAREA-LENGTH)
END-EXEC
.
2000-PROCESS-INPUT.
EVALUATE EIBAID
WHEN DFHPF3
EXEC CICS SEND TEXT
FROM(WS-GOODBYE-MSG)
LENGTH(WS-GOODBYE-LEN)
ERASE
FREEKB
END-EXEC
EXEC CICS RETURN END-EXEC
WHEN DFHPF12
PERFORM 1000-FIRST-TIME
WHEN DFHENTER
PERFORM 2100-HANDLE-ENTER
WHEN DFHCLEAR
EXEC CICS SEND TEXT
FROM(WS-GOODBYE-MSG)
LENGTH(WS-GOODBYE-LEN)
ERASE
FREEKB
END-EXEC
EXEC CICS RETURN END-EXEC
WHEN OTHER
MOVE LOW-VALUES TO CUSTMAPO
MOVE 'INVALID KEY - PF3=EXIT'
TO MSGEXTO
PERFORM 3000-SEND-MAP-DATAONLY
END-EVALUATE
.
2100-HANDLE-ENTER.
EXEC CICS RECEIVE MAP('CUSTMAP')
MAPSET('CUSTSET')
INTO(CUSTMAPI)
RESP(WS-CICS-RESP)
END-EXEC
IF WS-CICS-RESP = DFHRESP(MAPFAIL)
MOVE LOW-VALUES TO CUSTMAPO
MOVE 'PLEASE ENTER A CUSTOMER ID'
TO MSGEXTO
PERFORM 3000-SEND-MAP-DATAONLY
ELSE IF WS-CICS-RESP NOT = DFHRESP(NORMAL)
PERFORM 9100-UNEXPECTED-ERROR
ELSE
IF CUSTIDL = 0 OR CUSTIDI = SPACES
MOVE LOW-VALUES TO CUSTMAPO
MOVE 'CUSTOMER ID REQUIRED'
TO MSGEXTO
PERFORM 3000-SEND-MAP-DATAONLY
ELSE
MOVE CUSTIDI TO WS-CUST-KEY
PERFORM 2200-READ-CUSTOMER
END-IF
END-IF
.
2200-READ-CUSTOMER.
MOVE LENGTH OF WS-CUSTOMER-RECORD
TO WS-REC-LENGTH
EXEC CICS READ
FILE('CUSTFILE')
INTO(WS-CUSTOMER-RECORD)
RIDFLD(WS-CUST-KEY)
LENGTH(WS-REC-LENGTH)
RESP(WS-CICS-RESP)
RESP2(WS-CICS-RESP2)
END-EXEC
MOVE LOW-VALUES TO CUSTMAPO
EVALUATE WS-CICS-RESP
WHEN DFHRESP(NORMAL)
MOVE WS-CUST-KEY TO CUSTIDO
MOVE WS-CUST-NAME TO CUSTNMO
MOVE WS-CUST-BALANCE TO WS-BAL-DISPLAY
MOVE WS-BAL-DISPLAY TO CUSTBALO
MOVE 'CUSTOMER FOUND' TO MSGEXTO
MOVE WS-CUST-KEY TO CA-CUST-KEY
WHEN DFHRESP(NOTFND)
MOVE WS-CUST-KEY TO CUSTIDO
MOVE 'CUSTOMER NOT FOUND' TO MSGEXTO
WHEN DFHRESP(DISABLED)
MOVE 'CUSTOMER FILE IS DISABLED'
TO MSGEXTO
WHEN DFHRESP(NOTOPEN)
MOVE 'CUSTOMER FILE NOT OPEN'
TO MSGEXTO
WHEN OTHER
PERFORM 9100-UNEXPECTED-ERROR
END-EVALUATE
PERFORM 3000-SEND-MAP-DATAONLY
.
3000-SEND-MAP-DATAONLY.
EXEC CICS SEND MAP('CUSTMAP')
MAPSET('CUSTSET')
FROM(CUSTMAPO)
DATAONLY
FREEKB
CURSOR
END-EXEC
EXEC CICS RETURN
TRANSID('INQC')
COMMAREA(WS-COMMAREA)
LENGTH(WS-COMMAREA-LENGTH)
END-EXEC
.
9100-UNEXPECTED-ERROR.
EXEC CICS SEND TEXT
FROM(WS-ERROR-MSG)
LENGTH(80)
ERASE
FREEKB
END-EXEC
EXEC CICS RETURN END-EXEC
.
Summary
This chapter covered the fundamentals of CICS transaction processing with COBOL:
- CICS is IBM's online transaction processing monitor, handling billions of transactions daily on mainframes worldwide. It provides terminal management, task management, program management, file management, and recovery services.
- EXEC CICS...END-EXEC is the command-level interface for all CICS services, replacing native COBOL I/O statements.
- SEND TEXT and SEND MAP write output to the 3270 terminal. SEND MAP uses predefined BMS screen layouts for formatted displays.
- RECEIVE MAP reads user input from BMS-formatted screens, populating the symbolic map input structure.
- BMS (Basic Mapping Support) defines 3270 screen layouts using DFHMSD (mapset), DFHMDI (map), and DFHMDF (field) macros, with attribute bytes controlling field behavior (ASKIP, UNPROT, BRT, DRK, NUM, IC).
- File control commands (READ, WRITE, REWRITE, DELETE) provide random access to VSAM files, while browse commands (STARTBR, READNEXT, READPREV, ENDBR) provide sequential access.
- Pseudo-conversational programming is the fundamental CICS application design pattern. The task ends after sending the screen (RETURN TRANSID with COMMAREA) and a new task starts when the user responds. EIBCALEN distinguishes first invocations from subsequent ones.
- The EIB (Execute Interface Block) provides task information including EIBAID (which key was pressed), EIBCALEN (COMMAREA length), EIBTRNID (transaction ID), and EIBTRMID (terminal ID).
- Error handling uses RESP and RESP2 options on every CICS command, with DFHRESP symbolic constants (NORMAL, NOTFND, DUPREC, etc.) for readable error checking.
- Program control uses LINK (call and return) and XCTL (transfer without return) for navigation between CICS programs.
- TSQ and TDQ provide temporary storage and transient data capabilities for scratch pads, browse lists, logging, and inter-program communication.
- Compilation requires CICS translation (or integrated translation with COBOL V5+), COBOL compilation with CICS copylib, and link-editing with CICS stubs.
CICS programming represents a fundamentally different paradigm from batch COBOL. The pseudo-conversational model, the EXEC CICS command interface, and the BMS screen definition facility require new skills and new ways of thinking about program design. But the core language is still COBOL, and the principles of structured programming, defensive error handling, and clear naming conventions apply equally in the CICS environment.
CICS Programming: Key Restrictions and Differences from Batch
CICS imposes several restrictions on COBOL programs that batch programmers must understand before writing their first CICS application.
Prohibited Statements
The following COBOL statements are not allowed in CICS programs:
| Prohibited Statement | CICS Replacement |
|---|---|
| OPEN, CLOSE | File operations managed by CICS |
| READ, WRITE, REWRITE, DELETE (native) | EXEC CICS READ/WRITE/REWRITE/DELETE |
| ACCEPT | EXEC CICS RECEIVE |
| DISPLAY | EXEC CICS SEND TEXT (or write to TSQ/TDQ) |
| STOP RUN | EXEC CICS RETURN |
| SORT, MERGE | Not available in CICS (use batch) |
WORKING-STORAGE vs. LOCAL-STORAGE in CICS
In CICS, if multiple tasks execute the same program concurrently, they share the same copy of the program's code but (with IBM Enterprise COBOL V5+ and threadsafe programs) each task gets its own copy of WORKING-STORAGE. In older configurations, WORKING-STORAGE was shared, creating reentrancy problems. Modern CICS COBOL programs should always be compiled with the RENT (re-entrant) compiler option.
For maximum safety, use LOCAL-STORAGE instead of WORKING-STORAGE in CICS programs. LOCAL-STORAGE is allocated fresh for each task invocation and is automatically freed when the task ends:
LOCAL-STORAGE SECTION.
01 WS-CUSTOMER-RECORD.
05 WS-CUST-KEY PIC X(10).
05 WS-CUST-NAME PIC X(30).
05 WS-CUST-BALANCE PIC S9(7)V99 COMP-3.
Channel/Container Model (Modern CICS)
In CICS TS 3.1 and later, the channel/container model provides a modern alternative to the COMMAREA for passing data between programs. Containers are named data areas of virtually unlimited size, grouped into channels:
* Put data into a container
EXEC CICS PUT CONTAINER('CUSTDATA')
CHANNEL('CUSTCHAN')
FROM(WS-CUSTOMER-RECORD)
FLENGTH(LENGTH OF WS-CUSTOMER-RECORD)
END-EXEC
* Link to another program passing the channel
EXEC CICS LINK
PROGRAM('CUSTPROC')
CHANNEL('CUSTCHAN')
RESP(WS-CICS-RESP)
END-EXEC
* In the called program, retrieve the container
EXEC CICS GET CONTAINER('CUSTDATA')
CHANNEL('CUSTCHAN')
INTO(WS-CUSTOMER-RECORD)
FLENGTH(WS-DATA-LENGTH)
RESP(WS-CICS-RESP)
END-EXEC
The channel/container model overcomes the COMMAREA's 32KB size limitation and provides a more structured way to pass complex data between programs.
CICS Web Services
Modern CICS can expose COBOL programs as web services (SOAP or RESTful JSON). A COBOL program that follows good modular design practices (clear LINKAGE SECTION interface, no terminal I/O embedded in business logic) can be exposed as a web service with minimal or no code changes. CICS TS provides the PIPELINE facility for SOAP services and the URIMAP/PROGRAM mapping for RESTful services.
This capability means that COBOL business logic written decades ago can serve modern web and mobile front ends without rewriting the business rules. The COBOL program processes the business logic, and the CICS infrastructure handles the HTTP protocol, JSON/XML transformation, and security.
Exercises
-
SEND TEXT: Write a CICS program that sends a three-line welcome message to the terminal using SEND TEXT, then returns to CICS.
-
BMS Map Design: Design a BMS map for a simple employee inquiry screen with the following fields: employee ID (input), employee name (output), department (output), hire date (output), salary (output), and a message line. Write the DFHMSD/DFHMDI/DFHMDF macro definitions.
-
Pseudo-Conversational Inquiry: Write a complete pseudo-conversational CICS program that accepts an employee ID on the first screen, reads the employee record from a VSAM file, and displays the employee information. Handle PF3 (exit), PF12 (clear and restart), and Enter (search).
-
Error Handling: Add comprehensive error handling to the program from Exercise 3. Handle NOTFND, DISABLED, NOTOPEN, MAPFAIL, and unexpected errors. Log all unexpected errors to CSMT using WRITEQ TD.
-
Browse with TSQ: Write a CICS program that browses a VSAM file, stores the browse results in a TSQ (20 records per page), and allows the user to page forward (PF8) and backward (PF7) through the results. Use the TSQ item number to track the current page position.