Skip to content

feat: Migrate COBOL codebase to Spring Boot application (Phase 1 & 2)#70

Open
devin-ai-integration[bot] wants to merge 2 commits intomainfrom
devin/1773931233-cobol-to-spring-boot-migration
Open

feat: Migrate COBOL codebase to Spring Boot application (Phase 1 & 2)#70
devin-ai-integration[bot] wants to merge 2 commits intomainfrom
devin/1773931233-cobol-to-spring-boot-migration

Conversation

@devin-ai-integration
Copy link
Copy Markdown

@devin-ai-integration devin-ai-integration Bot commented Mar 19, 2026

Summary

Adds a spring-boot-app/ directory containing a Java Spring Boot application that migrates the COBOL example programs. This covers Phase 1 (project skeleton) and Phase 2 (data layer migration):

  • Entities: Account (JPA, from sql/sql_example.cbl WORKING-STORAGE), Customer (POJO, from merge_sort/merge_sort_test.cbl)
  • Repository: AccountRepository with Spring Data query methods replacing the three COBOL SQL cursors (ACCOUNT-ALL-CUR, ACCOUNT-DISABLED-CUR, ACCOUNT-QUERY-CUR)
  • Services: AccountService, SerializationService (JSON/XML via Jackson), SubProgramService (CALL BY CONTENT/REFERENCE pattern), SearchService (binary search replacing SEARCH ALL)
  • Controllers: AccountController (3 GET endpoints replacing the COBOL menu), SerializationController (POST endpoints for JSON/XML serialization)
  • Tests: 26 tests (repository integration with H2, service unit tests with Mockito, @WebMvcTest controller tests, search behavior tests) — all passing
  • README: Full COBOL-to-Java mapping tables, API docs, build/run instructions

No existing COBOL files were modified.

Updates since last revision

  • Fixed Account.enabled boolean ↔ VARCHAR('Y'/'N') mapping: Added @Convert(converter = YesNoConverter.class) using Hibernate's built-in converter so the enabled field correctly translates between Java boolean and the 'Y'/'N' strings stored in the production PostgreSQL IS_ENABLED column. Previously this would have broken at runtime against the real database.

Review & Testing Checklist for Human

  • Verify YesNoConverter works against real PostgreSQL: The converter has been added, but tests run against H2 with create-drop (which creates a native boolean column). Confirm that findByEnabledFalseOrderByIdAsc() generates correct SQL (IS_ENABLED = 'N') against the actual PostgreSQL VARCHAR(1) column.
  • jackson-dataformat-xml version 2.17.0 is pinned explicitly while Spring Boot 3.2.5 BOM manages Jackson at ~2.15.x. Verify no runtime conflicts between Jackson modules — safer to remove the <version> and let the BOM manage it.
  • SubProgramService holds mutable state (workingStorageItem1/2) in a singleton @Service bean — this is not thread-safe under concurrent HTTP requests. Consider whether this is acceptable as a demonstration or needs scoping (@RequestScope) or synchronization.
  • No .gitignore in spring-boot-app/target/, .classpath, .project, .settings/ were manually excluded from this commit but will reappear in git status for anyone who builds locally.
  • Hardcoded DB credentials in application.properties (postgres/password) — inherited from the COBOL source, but verify this is acceptable or should use env vars/profiles.

Recommended test plan:

  1. cd spring-boot-app && mvn clean test — confirm all 26 tests pass
  2. Stand up a local PostgreSQL with psql -f ../sql/create_test_db.sql, run mvn spring-boot:run, and hit the three account endpoints with curl — verify the IS_ENABLED Y/N values are correctly mapped to boolean
  3. Test the serialization endpoints (POST /api/serialize/json and /xml) with the curl examples in the README

Notes

  • SearchService and SubProgramService are standalone service beans with no REST endpoints wired to them — they exist as pattern demonstrations per the migration plan
  • No global error handling (@ControllerAdvice) yet — JsonProcessingException from the serialization controller will surface as a raw 500

Link to Devin session: https://app.devin.ai/sessions/ad38878f26b640d2a8fa48bc3f5321f7
Requested by: @jerryoliphant-cog


Open with Devin

- Create Spring Boot project structure with Maven build (pom.xml)
- Add JPA entity (Account) mapped from COBOL WORKING-STORAGE records
- Add Customer POJO from merge_sort file descriptor records
- Add AccountRepository with Spring Data JPA query methods replacing SQL cursors
- Add AccountService replacing PROCEDURE DIVISION paragraphs
- Add SerializationService replacing JSON/XML GENERATE statements
- Add SubProgramService demonstrating CALL BY CONTENT/REFERENCE patterns
- Add SearchService implementing binary search (SEARCH ALL equivalent)
- Add REST controllers replacing terminal-based ACCEPT/DISPLAY menu
- Add SerializationRecord DTO with @JsonProperty annotations for NAME OF mappings
- Add comprehensive tests (repository, service, controller, search)
- Add README with COBOL-to-Java migration mapping documentation
- All 26 tests passing

Co-Authored-By: Jerry Oliphant <jerry.oliphant@cognition.ai>
@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 and CI monitoring

Copy link
Copy Markdown
Author

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

Choose a reason for hiding this comment

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

Devin Review found 1 potential issue.

View 5 additional findings in Devin Review.

Open in Devin Review

Comment on lines +53 to +54
@Column(name = "IS_ENABLED", nullable = false)
private boolean enabled;
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.

🔴 Boolean field enabled is incompatible with VARCHAR(1) 'Y'/'N' column in production database

The Account.enabled field is mapped as a Java boolean (model/Account.java:54), but the production database schema defines is_enabled as VARCHAR(1) storing 'Y' or 'N' (schema.sql:15), and the existing seed data in sql/create_test_db.sql:23-53 uses those string values. Hibernate does not automatically convert between 'Y'/'N' strings and Java boolean — there is no @Convert or AttributeConverter registered anywhere in the project. This causes two failures at runtime against the production PostgreSQL database: (1) reading existing rows with 'Y'/'N' values will fail to deserialize into boolean, and (2) derived query methods like findByEnabledFalseOrderByIdAsc() will generate SQL comparing the VARCHAR column to a boolean literal rather than 'N'. Tests pass because application-test.properties uses ddl-auto=create-drop, which creates the column as a native BOOLEAN from the entity definition, bypassing the schema.sql entirely.

Fix options

Either add a JPA AttributeConverter to convert between 'Y'/'N' and boolean, e.g.:

@Convert(converter = YesNoConverter.class)
@Column(name = "IS_ENABLED", nullable = false)
private boolean enabled;

Or change the database schema to use a native BOOLEAN column and migrate existing data.

Prompt for agents
In spring-boot-app/src/main/java/com/cobolmigration/model/Account.java, the `enabled` field (lines 53-54) is a Java `boolean` mapped to a VARCHAR(1) column that stores 'Y'/'N'. Hibernate cannot automatically convert between these types.

Fix by adding a Hibernate @Convert annotation with a built-in or custom converter. The simplest approach with Hibernate 6 (used in Spring Boot 3.x) is:

1. Add `import org.hibernate.type.YesNoConverter;` and `import jakarta.persistence.Convert;` to Account.java
2. Change the field annotation to:
   @Convert(converter = YesNoConverter.class)
   @Column(name = "IS_ENABLED", nullable = false)
   private boolean enabled;

Alternatively, create a custom AttributeConverter<Boolean, String> that maps true->'Y' and false->'N', and apply it with @Convert.

Also update spring-boot-app/src/main/resources/schema.sql line 15 to be consistent - either keep VARCHAR(1) and use the converter, or change the column to BOOLEAN and update the seed data.
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.

Fixed in 5f68f00 — added @Convert(converter = YesNoConverter.class) using Hibernate's built-in converter to properly translate between Java boolean and the VARCHAR(1) 'Y'/'N' values in the production database. All 26 tests still pass.

…) column

Addresses Devin Review finding: boolean field was incompatible with
the production PostgreSQL IS_ENABLED VARCHAR(1) column storing 'Y'/'N'.
Uses Hibernate's built-in YesNoConverter to properly convert between
Java boolean and the database character values.

Co-Authored-By: Jerry Oliphant <jerry.oliphant@cognition.ai>
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.

0 participants