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

  1. Search by account number or customer name
  2. Display all account fields with editable overlays for authorized fields
  3. Validate all changes before applying
  4. Show a before/after confirmation screen
  5. Prevent concurrent update conflicts (two staff editing the same account)
  6. Maintain a complete audit trail of all changes
  7. 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.

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

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

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

  3. Validation programs should be independent. By separating validation into a LINKable program, the team avoided duplicating rules across three different interfaces.

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

  1. 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?
  2. The team chose not to use channels/containers for this transaction. What advantages would channels/containers have offered? What migration effort would be required?
  3. How would you extend this design to support a "maker/checker" workflow where one person makes changes and a supervisor must approve them?
  4. What happens if the AUDT trigger-level processing transaction abends? Are audit records lost?