feat: Migrate COBOL codebase to Spring Boot application (Phase 1 & 2)#70
feat: Migrate COBOL codebase to Spring Boot application (Phase 1 & 2)#70devin-ai-integration[bot] wants to merge 2 commits intomainfrom
Conversation
- 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 EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
| @Column(name = "IS_ENABLED", nullable = false) | ||
| private boolean enabled; |
There was a problem hiding this comment.
🔴 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.
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
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>
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):Account(JPA, fromsql/sql_example.cblWORKING-STORAGE),Customer(POJO, frommerge_sort/merge_sort_test.cbl)AccountRepositorywith Spring Data query methods replacing the three COBOL SQL cursors (ACCOUNT-ALL-CUR,ACCOUNT-DISABLED-CUR,ACCOUNT-QUERY-CUR)AccountService,SerializationService(JSON/XML via Jackson),SubProgramService(CALL BY CONTENT/REFERENCE pattern),SearchService(binary search replacing SEARCH ALL)AccountController(3 GET endpoints replacing the COBOL menu),SerializationController(POST endpoints for JSON/XML serialization)@WebMvcTestcontroller tests, search behavior tests) — all passingNo existing COBOL files were modified.
Updates since last revision
Account.enabledboolean ↔ VARCHAR('Y'/'N') mapping: Added@Convert(converter = YesNoConverter.class)using Hibernate's built-in converter so theenabledfield correctly translates between Javabooleanand the'Y'/'N'strings stored in the production PostgreSQLIS_ENABLEDcolumn. Previously this would have broken at runtime against the real database.Review & Testing Checklist for Human
YesNoConverterworks against real PostgreSQL: The converter has been added, but tests run against H2 withcreate-drop(which creates a native boolean column). Confirm thatfindByEnabledFalseOrderByIdAsc()generates correct SQL (IS_ENABLED = 'N') against the actual PostgreSQLVARCHAR(1)column.jackson-dataformat-xmlversion 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.SubProgramServiceholds mutable state (workingStorageItem1/2) in a singleton@Servicebean — this is not thread-safe under concurrent HTTP requests. Consider whether this is acceptable as a demonstration or needs scoping (@RequestScope) or synchronization..gitignoreinspring-boot-app/—target/,.classpath,.project,.settings/were manually excluded from this commit but will reappear ingit statusfor anyone who builds locally.application.properties(postgres/password) — inherited from the COBOL source, but verify this is acceptable or should use env vars/profiles.Recommended test plan:
cd spring-boot-app && mvn clean test— confirm all 26 tests passpsql -f ../sql/create_test_db.sql, runmvn spring-boot:run, and hit the three account endpoints withcurl— verify theIS_ENABLEDY/N values are correctly mapped to booleanPOST /api/serialize/jsonand/xml) with the curl examples in the READMENotes
SearchServiceandSubProgramServiceare standalone service beans with no REST endpoints wired to them — they exist as pattern demonstrations per the migration plan@ControllerAdvice) yet —JsonProcessingExceptionfrom the serialization controller will surface as a raw 500Link to Devin session: https://app.devin.ai/sessions/ad38878f26b640d2a8fa48bc3f5321f7
Requested by: @jerryoliphant-cog