diff --git a/.gitignore b/.gitignore
index cf3f6b1..8434d98 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
**/bin
+**/target/
diff --git a/java-migration/pom.xml b/java-migration/pom.xml
new file mode 100644
index 0000000..2891bc6
--- /dev/null
+++ b/java-migration/pom.xml
@@ -0,0 +1,103 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.2.5
+
+
+
+ com.example
+ cobol-migration
+ 0.0.1-SNAPSHOT
+ cobol-migration
+ Java Spring Boot migration of COBOL Examples
+
+
+ 17
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
+
+
+
+ org.postgresql
+ postgresql
+ runtime
+
+
+
+
+ org.flywaydb
+ flyway-core
+
+
+
+
+
+ com.fasterxml.jackson.dataformat
+ jackson-dataformat-xml
+
+
+
+
+ jakarta.xml.bind
+ jakarta.xml.bind-api
+
+
+ org.glassfish.jaxb
+ jaxb-runtime
+
+
+
+
+ org.apache.poi
+ poi
+ 5.2.5
+
+
+ org.apache.poi
+ poi-ooxml
+ 5.2.5
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ com.h2database
+ h2
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
diff --git a/java-migration/src/main/java/com/example/cobolmigration/CobolMigrationApplication.java b/java-migration/src/main/java/com/example/cobolmigration/CobolMigrationApplication.java
new file mode 100644
index 0000000..ad68318
--- /dev/null
+++ b/java-migration/src/main/java/com/example/cobolmigration/CobolMigrationApplication.java
@@ -0,0 +1,12 @@
+package com.example.cobolmigration;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class CobolMigrationApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(CobolMigrationApplication.class, args);
+ }
+}
diff --git a/java-migration/src/main/java/com/example/cobolmigration/config/AppConfig.java b/java-migration/src/main/java/com/example/cobolmigration/config/AppConfig.java
new file mode 100644
index 0000000..f82cfec
--- /dev/null
+++ b/java-migration/src/main/java/com/example/cobolmigration/config/AppConfig.java
@@ -0,0 +1,62 @@
+package com.example.cobolmigration.config;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.dao.DataAccessException;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+
+/**
+ * Application configuration and global exception handling.
+ *
+ * The {@link GlobalExceptionHandler} replaces the COBOL check-sql-state
+ * paragraph (sql/sql_example.cbl lines 443-472) which checks SQLCODE /
+ * SQLSTATE and terminates on error. Instead of terminating, we return
+ * appropriate HTTP error responses.
+ */
+@Configuration
+public class AppConfig {
+
+ @RestControllerAdvice
+ public static class GlobalExceptionHandler {
+
+ /**
+ * Handles database access errors, replacing the COBOL pattern of
+ * checking SQLCODE after every EXEC SQL statement.
+ */
+ @ExceptionHandler(DataAccessException.class)
+ public ResponseEntity handleDataAccessException(
+ DataAccessException ex) {
+ ErrorResponse error = new ErrorResponse(
+ "Database error",
+ ex.getMostSpecificCause().getMessage());
+ return ResponseEntity
+ .status(HttpStatus.INTERNAL_SERVER_ERROR)
+ .body(error);
+ }
+
+ @ExceptionHandler(IllegalArgumentException.class)
+ public ResponseEntity handleIllegalArgument(
+ IllegalArgumentException ex) {
+ ErrorResponse error = new ErrorResponse(
+ "Invalid request", ex.getMessage());
+ return ResponseEntity
+ .status(HttpStatus.BAD_REQUEST)
+ .body(error);
+ }
+
+ @ExceptionHandler(Exception.class)
+ public ResponseEntity handleGenericException(
+ Exception ex) {
+ ErrorResponse error = new ErrorResponse(
+ "Internal server error", ex.getMessage());
+ return ResponseEntity
+ .status(HttpStatus.INTERNAL_SERVER_ERROR)
+ .body(error);
+ }
+ }
+
+ public record ErrorResponse(String error, String detail) {
+ }
+}
diff --git a/java-migration/src/main/java/com/example/cobolmigration/controller/AccountController.java b/java-migration/src/main/java/com/example/cobolmigration/controller/AccountController.java
new file mode 100644
index 0000000..391c742
--- /dev/null
+++ b/java-migration/src/main/java/com/example/cobolmigration/controller/AccountController.java
@@ -0,0 +1,59 @@
+package com.example.cobolmigration.controller;
+
+import com.example.cobolmigration.entity.Account;
+import com.example.cobolmigration.service.AccountService;
+import java.util.List;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * REST controller replacing the terminal-based menu system from
+ * sql/sql_example.cbl (lines 155-186).
+ *
+ * COBOL menu option mapping:
+ * 1) Display all accounts -> GET /api/accounts
+ * 2) Display disabled accounts -> GET /api/accounts/disabled
+ * 3) Query accounts -> GET /api/accounts/search?q={value}
+ * 4) Exit -> (not applicable for REST)
+ */
+@RestController
+@RequestMapping("/api/accounts")
+public class AccountController {
+
+ private final AccountService accountService;
+
+ public AccountController(AccountService accountService) {
+ this.accountService = accountService;
+ }
+
+ /**
+ * Replaces menu option "1) Display all accounts".
+ */
+ @GetMapping
+ public ResponseEntity> getAllAccounts() {
+ return ResponseEntity.ok(accountService.getAllAccounts());
+ }
+
+ /**
+ * Replaces menu option "2) Display disabled accounts".
+ */
+ @GetMapping("/disabled")
+ public ResponseEntity> getDisabledAccounts() {
+ return ResponseEntity.ok(accountService.getDisabledAccounts());
+ }
+
+ /**
+ * Replaces menu option "3) Query accounts".
+ *
+ * The COBOL implementation wraps the trimmed search value with '%'
+ * wildcards and queries across FIRST_NAME, LAST_NAME, PHONE, and ADDRESS.
+ */
+ @GetMapping("/search")
+ public ResponseEntity> searchAccounts(
+ @RequestParam("q") String searchValue) {
+ return ResponseEntity.ok(accountService.searchAccounts(searchValue));
+ }
+}
diff --git a/java-migration/src/main/java/com/example/cobolmigration/controller/DemoController.java b/java-migration/src/main/java/com/example/cobolmigration/controller/DemoController.java
new file mode 100644
index 0000000..342f615
--- /dev/null
+++ b/java-migration/src/main/java/com/example/cobolmigration/controller/DemoController.java
@@ -0,0 +1,120 @@
+package com.example.cobolmigration.controller;
+
+import com.example.cobolmigration.dto.JsonRecord;
+import com.example.cobolmigration.dto.SearchItem;
+import com.example.cobolmigration.service.ReportService;
+import com.example.cobolmigration.service.ReportService.StudentRecord;
+import com.example.cobolmigration.service.SerializationService;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * REST controller demonstrating the non-SQL COBOL module equivalents:
+ * JSON generation, XML generation, report writing, search table, and
+ * CLI argument handling.
+ */
+@RestController
+@RequestMapping("/api/demo")
+public class DemoController {
+
+ private final SerializationService serializationService;
+ private final ReportService reportService;
+
+ public DemoController(SerializationService serializationService,
+ ReportService reportService) {
+ this.serializationService = serializationService;
+ this.reportService = reportService;
+ }
+
+ /**
+ * Demonstrates JSON generation replacing json_generate/json_generate.cbl.
+ */
+ @GetMapping("/json")
+ public ResponseEntity jsonDemo() {
+ JsonRecord sample = serializationService.createSampleJsonRecord();
+ return ResponseEntity.ok(sample);
+ }
+
+ /**
+ * Demonstrates XML generation replacing xml_generate/xml_generate.cbl.
+ * Returns the raw XML string with the XML declaration.
+ */
+ @GetMapping(value = "/xml", produces = MediaType.APPLICATION_XML_VALUE)
+ public ResponseEntity xmlDemo() {
+ String xml = serializationService.generateXml(
+ serializationService.createSampleXmlRecord());
+ return ResponseEntity.ok(xml);
+ }
+
+ /**
+ * Generates a text report replacing report_writer/report_test.cbl.
+ * Accepts an optional format parameter (text or csv).
+ */
+ @GetMapping(value = "/report", produces = MediaType.TEXT_PLAIN_VALUE)
+ public ResponseEntity reportDemo(
+ @RequestParam(value = "format", defaultValue = "text") String format) {
+ List sampleData = List.of(
+ new StudentRecord(334500, "Alice Johnson", "CSC", 5),
+ new StudentRecord(334501, "Bob Smith", "PHY", 12),
+ new StudentRecord(334502, "Carol White", "MAT", 8),
+ new StudentRecord(334503, "David Brown", "ENG", 3));
+
+ String report;
+ if ("csv".equalsIgnoreCase(format)) {
+ report = reportService.generateCsvReport(sampleData);
+ } else {
+ report = reportService.generateTextReport(sampleData);
+ }
+ return ResponseEntity.ok(report);
+ }
+
+ /**
+ * Demonstrates binary search on a sorted table, replacing
+ * search/search.cbl SEARCH ALL behaviour.
+ *
+ * Populates a list with the same test data as the COBOL program's
+ * setup-test-data paragraph and performs a binary search by id1.
+ */
+ @GetMapping("/search")
+ public ResponseEntity