Case Study 1: GlobalBank's Multi-Screen Account Maintenance Transaction
Background
GlobalBank's branch staff previously updated account information through a cumbersome process: fill out a paper form, fax it to the operations center, and wait 24-48 hours for an operator to key the changes into a batch update program. This process was slow, error-prone (transcription errors from fax), and created a 1-2 day lag between customer requests and account changes.
Maria Chen's team was tasked with building an online account maintenance transaction (AMNT) that allows authorized branch staff to update account information in real time.
Requirements
- Search by account number or customer name
- Display all account fields with editable overlays for authorized fields
- Validate all changes before applying
- Show a before/after confirmation screen
- Prevent concurrent update conflicts (two staff editing the same account)
- Maintain a complete audit trail of all changes
- Restrict access by role: tellers can change address only; supervisors can change type and status; managers can change all fields including branch assignment
Design Decisions
Decision 1: Optimistic Locking Over Pessimistic
Derek Washington initially proposed using SELECT FOR UPDATE to lock the account record when the edit screen was displayed. Maria rejected this:
"Think about what happens when a branch supervisor starts editing an account, then a customer walks up to the counter. The supervisor helps the customer for five minutes, then comes back to the screen. During those five minutes, every other transaction — online inquiries, ATM withdrawals, the batch interest calculation — is blocked on that one account. Optimistic locking is the only viable option in a pseudo-conversational environment."
The team implemented optimistic locking by storing original field values in the COMMAREA and including them in the UPDATE's WHERE clause.
Decision 2: TSQ for Audit Trail Buffer
Rather than writing each audit record to DB2 within the update transaction (which adds to its elapsed time), the team writes audit records to an intrapartition TDQ with a trigger level of 50. When 50 records accumulate, CICS starts transaction AUDT which batch-inserts them into DB2. This keeps the maintenance transaction fast while ensuring audit records are persisted.
Decision 3: LINK to a Shared Validation Program
Field validation logic was placed in a separate program (ACCTVAL) called via LINK. This same validation program is reused by: - The CICS maintenance transaction - A batch correction program - A future REST API endpoint
This follows the "write once, validate everywhere" principle.
Implementation Highlights
The State Machine
The transaction uses five states:
| State | Screen | Next States |
|---|---|---|
| S (Search) | Account search | E (found), S (not found) |
| E (Edit) | Edit account fields | C (changes made), S (PF3 cancel) |
| C (Confirm) | Before/after review | S (commit success), E (cancel) |
| R (Retry) | Edit after conflict | C (changes made), S (cancel) |
| X (Conflict) | Conflict notification | R (retry with new values), S (cancel) |
Handling the Concurrent Update Conflict
When the UPDATE's WHERE clause does not match (SQLERRD(3) = 0), the program: 1. Re-reads the current record from DB2 2. Compares the new current values with the user's changes to identify true conflicts 3. If only non-overlapping fields changed, merges automatically 4. If the same field was changed by both users, displays the conflict screen with three values: user's original, user's change, and current database value
This sophisticated conflict resolution was added after a production incident where two supervisors edited the same account simultaneously and one supervisor's changes were silently lost.
Role-Based Field Protection
The program uses RACF-based authorization and BMS attribute manipulation:
* Check user's authorization level
EXEC CICS ASSIGN USERID(WS-USER-ID) END-EXEC
EXEC CICS QUERY SECURITY RESTYPE('TRANSATTACH')
RESID('AMTS') ... END-EXEC
* Set field attributes based on role
IF WS-ROLE = 'TELLER'
MOVE DFHBMPRF TO ATYPEF (protect type)
MOVE DFHBMPRF TO ASTATF (protect status)
MOVE DFHBMPRF TO ABRANCHF (protect branch)
END-IF
Results
| Metric | Before (Paper) | After (CICS) |
|---|---|---|
| Change turnaround | 24-48 hours | Immediate |
| Transcription errors | ~5% of changes | 0% (validated) |
| Unauthorized changes | Difficult to prevent | Role-enforced |
| Audit trail | Paper forms, often lost | Complete DB2 audit table |
| Concurrent conflict resolution | Last writer wins | Detected and resolved |
Lessons Learned
-
Optimistic locking is essential in pseudo-conversational transactions. Pessimistic locking is simply not compatible with the pseudo-conversational model where tasks end between user interactions.
-
Conflict detection must go beyond "update failed." Simply telling the user "someone else changed the record" is not helpful. Showing which fields conflicted and letting the user merge changes dramatically reduces frustration.
-
Validation programs should be independent. By separating validation into a LINKable program, the team avoided duplicating rules across three different interfaces.
-
Audit via TDQ decouples logging from transaction speed. Writing audit records to a TDQ with trigger-level processing added zero perceivable latency to the maintenance transaction.
Discussion Questions
- Why was the COMMAREA large enough to store both original and new values for editable fields? Could the original values be stored in a TSQ instead? What trade-offs would that involve?
- The team chose not to use channels/containers for this transaction. What advantages would channels/containers have offered? What migration effort would be required?
- How would you extend this design to support a "maker/checker" workflow where one person makes changes and a supervisor must approve them?
- What happens if the AUDT trigger-level processing transaction abends? Are audit records lost?