Event-driven programming in COBOL means writing code that reacts to events (conditions) when they happen, instead of looping and testing. Typical events are end-of-file (AT END), invalid key on indexed files (INVALID KEY), and in CICS, conditions such as NOTFND or ERROR handled with HANDLE CONDITION. This page introduces the ideas and shows common patterns.
An event is something that occurs during execution and to which the program can respond. The run time or CICS transfers control to a block of code you specify (a paragraph or a scope) when the event happens. You do not have to poll; you set up the response once, then run your main logic.
| Event / clause | Meaning |
|---|---|
| AT END (READ) | Triggered when a sequential read reaches end-of-file |
| INVALID KEY | Triggered when an indexed key is not found or duplicate (depends on usage) |
| HANDLE CONDITION (CICS) | Triggered when a CICS condition (e.g. NOTFND, ERROR) occurs |
| END-READ / END-WRITE | Explicit end of READ/WRITE scope; can contain exception handling |
When you READ a file, you can say what to do when there are no more records by using AT END. When you use an indexed file and the key is not found (or duplicate, depending on the verb), INVALID KEY runs. These are event-driven: the I/O system raises the “event” and your code runs in response.
12345678910111213141516*> Event: end-of-file. When READ hits end of file, control goes to the AT END block. READ INFILE AT END SET WS-EOF TO TRUE *> Your end-of-file handling (e.g. close files, final totals) NOT AT END PERFORM PROCESS-RECORD END-READ. *> Event: invalid key (e.g. key not found on indexed READ) READ INDEXED-FILE INVALID KEY DISPLAY "Key not found: " WS-KEY NOT INVALID KEY PERFORM USE-RECORD END-READ.
AT END and NOT AT END are the two branches for the “end of file” event. INVALID KEY and NOT INVALID KEY are the two branches for the “invalid key” event. END-READ marks the end of the READ scope (see Scope terminators).
In CICS, you register handlers for conditions. When that condition occurs anywhere in the program, CICS transfers control to the label you gave. That is event-driven: you do not test the condition in every paragraph; you say “when NOTFND (or ERROR, etc.) happens, go to this paragraph.”
1234567891011121314151617*> Register what to do when the NOTFND (key not found) "event" occurs EXEC CICS HANDLE CONDITION NOTFND(NOT-FOUND-PARA) ERROR(ERROR-PARA) END-EXEC. *> Main logic; if a later CICS command gets NOTFND, control goes to NOT-FOUND-PARA EXEC CICS READ FILE(FILE-NAME) RIDFLD(WS-KEY) ... END-EXEC. *> If key not found, we never get here; control is in NOT-FOUND-PARA NOT-FOUND-PARA. *> Handle "key not found" event ... ERROR-PARA. *> Handle CICS error event ...
Use event-driven clauses when the run time or CICS already “knows” when something happened (end-of-file, invalid key, CICS condition). Let the system hand control to your handler instead of checking return codes in every paragraph. For normal branching (e.g. “if balance < 0”), use IF/EVALUATE; for I/O and CICS conditions, use the event clauses and HANDLE CONDITION.
1. What does AT END on a READ statement do?
2. In CICS, what does HANDLE CONDITION do?