Skip to content

feat: Java 17+ rewrite of CBACT01C batch program with system analysis - #219

Open
devin-ai-integration[bot] wants to merge 3 commits into
mainfrom
devin/1782308891-cbact01c-java-rewrite
Open

devin-ai-integration[bot] wants to merge 3 commits into
mainfrom
devin/1782308891-cbact01c-java-rewrite

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Jun 24, 2026

Copy link
Copy Markdown

Summary

Rewrites the COBOL batch program CBACT01C.cbl as a Java 17+ application and adds a full system analysis document.

What CBACT01C does: Reads the VSAM KSDS account master sequentially and fans each record out to three output files in different formats -- flat fixed-length (OUTFILE), array-structured with 5 OCCURS slots (ARRYFILE), and variable-length with two record layouts per account (VBRCFILE). Key transformations: date reformatting via COBDATFT (YYYY-MM-DD → YYYYMMDD), default-value substitution (ACCT-CURR-CYC-DEBIT == 02525.00), and hardcoded array slot population.

New files:

  • docs/SYSTEM_ANALYSIS.md -- Documents business logic flow, CVACT01Y/CODATECN copybook-to-Java type mappings, I/O operations, external dependencies (COBDATFT, CEE3ABD), and all edge cases/error handling paths.

  • java-app/ -- Maven project (Java 17, JUnit 5) with:

    • AccountFileProcessor -- main batch driver mirroring the COBOL procedure division paragraphs
    • AccountRecord.parse() -- parses 300-byte fixed-length lines matching CVACT01Y layout, including COBOL zoned-decimal trailing overpunch decoding ({A-I positive, }J-R negative)
    • DateConverter -- replaces the COBDATFT assembler program; constants YYYYMMDD/YYYY_MM_DD match their names for both input and output
    • OutAccountRecord, ArrayAccountRecord, VbrRecord1, VbrRecord2 -- Java records for each output format
    • 25 JUnit tests covering: end-to-end multi-record flow, zero-debit default substitution, date conversion round-trips, array slot population, VBR record lengths, empty-file handling, missing-file error paths, production data parsing with overpunch encoding, and negative value handling

Link to Devin session: https://partner-workshops.devinenterprise.com/sessions/fad0316aab00417e9dec4073c66150ae
Requested by: @bsmitches


Open in Devin Review

- Add docs/SYSTEM_ANALYSIS.md with full business logic, data structure,
  I/O, dependency, and edge-case analysis of CBACT01C.cbl
- Add java-app Maven project (Java 17, JUnit 5) implementing the batch
  account file processor with equivalent behavior
- 21 JUnit tests covering end-to-end flow, transformation rules,
  date conversion, output formats, and error handling
@bsmitches bsmitches self-assigned this Jun 24, 2026
@devin-ai-integration

Copy link
Copy Markdown
Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 2 potential issues.

Open in Devin Review

Comment thread java-app/src/main/java/com/carddemo/util/DateConverter.java
Comment on lines +28 to +34
private static String formatDecimal(BigDecimal val) {
boolean negative = val.signum() < 0;
BigDecimal abs = val.abs();
long unscaled = abs.movePointRight(2).longValue();
String digits = String.format("%012d", unscaled);
return (negative ? "-" : "+") + digits;
}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚩 Output record sizes differ from COBOL due to text-based sign representation

The formatDecimal method in OutAccountRecord.java:36-42, ArrayAccountRecord.java:28-34, and VbrRecord2.java:22-28 all produce 13-character strings (sign + 12 digits). In COBOL, PIC S9(10)V99 DISPLAY is 12 bytes (sign overpunched in last digit), and COMP-3 is 7 bytes (packed decimal). This means Java output record sizes differ from COBOL: e.g., VBR-REC2 is 41 chars in Java vs 39 bytes in COBOL, and ARR-ARRAY-REC is 145 chars vs 110 bytes. The test at line 407 validates the 145-char Java length. This is a consistent design choice for text-based output, but downstream consumers expecting COBOL-compatible fixed-width records will need to account for the different field widths.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Acknowledged. The 13-char format (explicit sign char + 12 digits) is a deliberate choice for the Java text-based output -- COBOL's overpunched signs and COMP-3 packed decimal don't have direct text equivalents. Downstream consumers expecting COBOL-compatible fixed-width records would need a binary serialization layer. For now this is documented in docs/SYSTEM_ANALYSIS.md (section 3.3, noting COMP-3 usage on OUT-ACCT-CURR-CYC-DEBIT).

The output switch cases were swapped: YYYYMMDD produced YYYY-MM-DD and
vice versa (inherited from COBOL's inverted type-code semantics for
input vs output). Now each constant produces the format its name
describes. Updated the caller in AccountFileProcessor and tests.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 3 new potential issues.

Open in Devin Review

Comment thread java-app/src/main/java/com/carddemo/model/AccountRecord.java
Comment on lines +17 to +26
public String toOutputLine() {
StringBuilder sb = new StringBuilder();
sb.append(String.format("%011d", acctId));
for (int i = 0; i < SLOT_COUNT; i++) {
sb.append(formatDecimal(balances[i]));
sb.append(formatDecimal(debits[i]));
}
sb.append(" "); // ARR-FILLER X(04)
return sb.toString();
}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚩 COMP-3 packed-decimal fields written as text, losing binary compatibility

In the original COBOL, OUT-ACCT-CURR-CYC-DEBIT (CBACT01C.cbl:67-68) and ARR-ACCT-CURR-CYC-DEBIT (CBACT01C.cbl:76-77) use USAGE IS COMP-3 (packed decimal, 7 bytes for S9(10)V99). The Java code writes these as the same text format as all other decimal fields (13-char sign+digits). This is a fundamental format change from binary to text. If any downstream system reads these output files expecting packed-decimal binary data, it would fail. This may be intentional for the modernization (text-only output), but it's not called out in the system analysis document.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Acknowledged -- this is the same design choice noted in the previous review round. The Java version intentionally uses text-based output (sign char + digits) rather than binary packed-decimal. This is a standard approach for modernization where downstream consumers are expected to be Java/text-based rather than mainframe-native. The COMP-3 usage in the original COBOL is already documented in docs/SYSTEM_ANALYSIS.md section 3.3.

…ignedDecimal

The parser now decodes trailing overpunch characters ({,A-I for positive;
},J-R for negative) used in the production data (app/data/ASCII/acctdata.txt).
Updated test helper to generate overpunch-encoded data matching the real format.
Added tests for production data line and negative overpunch values.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

Open in Devin Review

Comment on lines +84 to +87
VbrRecord1 vbr1 = populateVbrRecord1(account);
VbrRecord2 vbr2 = populateVbrRecord2(account);
writeRecord(vbrcWriter, vbr1.toOutputLine(), "VBRCFILE");
writeRecord(vbrcWriter, vbr2.toOutputLine(), "VBRCFILE");

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚩 COBOL VBRC file uses RECORDING MODE V (RDW headers); Java uses plain text lines

The COBOL VBRC-FILE declaration (CBACT01C.cbl:80-84) uses RECORDING MODE IS V with RECORD IS VARYING ... DEPENDING ON WS-RECD-LEN, meaning each physical record has a 4-byte Record Descriptor Word (RDW) prefix containing the record length. The Java implementation at AccountFileProcessor.java:86-87 writes plain text lines with newline delimiters. This is a fundamental format difference — the VB1 record is 12 bytes and VB2 is 39 bytes in COBOL, but in Java they are variable-length text lines. If the VBRC output needs to be consumed by programs expecting MVS variable-length record format, this won't work.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Acknowledged. Same design intent as the COMP-3 and record-size points from earlier rounds -- the Java version produces newline-delimited text output, not MVS binary VB format with RDW headers. This is the standard approach for a modernized Java application where downstream consumers are text/CSV-based rather than mainframe-native. If binary-compatible VB output is ever needed, a RecordDescriptorWord serialization layer could be added on top of the existing record models.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant