From a2b5197ec2c8303124fcd828d59befdeb3425e1e Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Thu, 2 Oct 2025 15:27:30 +0000 Subject: [PATCH] MBA-309: Migrate banking application from Java 8 to Java 11 - Updated Java version from 1.8 to 11 in pom.xml - Upgraded Spring Boot from 2.1.4.RELEASE to 2.7.18 - Replaced Springfox Swagger dependencies with SpringDoc OpenAPI 1.6.15 - Migrated Swagger annotations to OpenAPI 3.0 in controllers - Updated ApplicationConfig to use SpringDoc OpenAPI configuration - Migrated JUnit 4 tests to JUnit 5 (Jupiter) - Updated README.md with Java 11 requirements and new Swagger URL All tests pass and application starts successfully on Java 11. Co-Authored-By: Anke Hao --- README.md | 13 ++--- pom.xml | 16 +++--- .../bankapp/config/ApplicationConfig.java | 27 +++------- .../bankapp/controller/AccountController.java | 42 ++++++++-------- .../controller/CustomerController.java | 50 +++++++++---------- .../bankapp/BankingApplicationTests.java | 5 +- 6 files changed, 68 insertions(+), 85 deletions(-) diff --git a/README.md b/README.md index 991b41a..b76a2b2 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Banking Application using Java8, Spring Boot, Spring Security and H2 DB +# Banking Application using Java 11, Spring Boot, Spring Security and H2 DB RESTful API to simulate simple banking operations. @@ -38,9 +38,9 @@ https://projectlombok.org/setup/eclipse ### Prerequisites -* Java 8 +* Java 11 JDK (ensure JAVA_HOME environment variable is set to Java 11 installation) * Spring Tool Suite 4 or similar IDE -* [Maven](https://maven.apache.org/) - Dependency Management +* [Maven](https://maven.apache.org/) 3.6+ - Dependency Management ### Maven Dependencies @@ -52,8 +52,7 @@ spring-boot-starter-web spring-boot-devtools h2 - Inmemory database lombok - to reduce boilerplate code -springfox-swagger2 -springfox-swagger-ui +springdoc-openapi-ui - OpenAPI 3.0 documentation spring-boot-starter-test spring-security-test @@ -64,10 +63,12 @@ spring-security-test Please find the Rest API documentation in the below url ``` -http://localhost:8989/bank-api/swagger-ui.html +http://localhost:8989/bank-api/swagger-ui/index.html ``` +Note: SpringDoc OpenAPI uses a different URL pattern than the legacy Springfox implementation. + ## H2 In-Memory Database Make sure to use jdbc:h2:mem:testdb as your jdbc url. If you intend to you use custom database name, please diff --git a/pom.xml b/pom.xml index 36931d2..797732f 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.boot spring-boot-starter-parent - 2.1.4.RELEASE + 2.7.18 com.coding.exercise @@ -15,7 +15,7 @@ Bank App Spring Boot Project - 1.8 + 11 @@ -52,15 +52,11 @@ true - io.springfox - springfox-swagger2 - 2.9.2 + org.springdoc + springdoc-openapi-ui + 1.6.15 - - io.springfox - springfox-swagger-ui - 2.10.0 - + org.springframework.boot spring-boot-starter-test diff --git a/src/main/java/com/coding/exercise/bankapp/config/ApplicationConfig.java b/src/main/java/com/coding/exercise/bankapp/config/ApplicationConfig.java index 67845f3..0df0ffe 100644 --- a/src/main/java/com/coding/exercise/bankapp/config/ApplicationConfig.java +++ b/src/main/java/com/coding/exercise/bankapp/config/ApplicationConfig.java @@ -3,29 +3,18 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import springfox.documentation.builders.ApiInfoBuilder; -import springfox.documentation.builders.PathSelectors; -import springfox.documentation.service.ApiInfo; -import springfox.documentation.spi.DocumentationType; -import springfox.documentation.spring.web.plugins.Docket; -import springfox.documentation.swagger2.annotations.EnableSwagger2; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.info.Info; @Configuration -@EnableSwagger2 public class ApplicationConfig { @Bean - public Docket api() { - return new Docket(DocumentationType.SWAGGER_2) - .apiInfo(apiInfo()) - .select() - .paths(PathSelectors.any()) - .build(); - } - - private ApiInfo apiInfo() { - return new ApiInfoBuilder().title("BANKING APPLICATION REST API") - .description("API for Banking Application.") - .version("1.0.0").build(); + public OpenAPI customOpenAPI() { + return new OpenAPI() + .info(new Info() + .title("BANKING APPLICATION REST API") + .description("API for Banking Application.") + .version("1.0.0")); } } diff --git a/src/main/java/com/coding/exercise/bankapp/controller/AccountController.java b/src/main/java/com/coding/exercise/bankapp/controller/AccountController.java index b35f625..d0038e2 100644 --- a/src/main/java/com/coding/exercise/bankapp/controller/AccountController.java +++ b/src/main/java/com/coding/exercise/bankapp/controller/AccountController.java @@ -17,24 +17,24 @@ import com.coding.exercise.bankapp.domain.TransferDetails; import com.coding.exercise.bankapp.service.BankingServiceImpl; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; @RestController @RequestMapping("accounts") -@Api(tags = { "Accounts and Transactions REST endpoints" }) +@Tag(name = "Accounts and Transactions REST endpoints") public class AccountController { @Autowired private BankingServiceImpl bankingService; @GetMapping(path = "/{accountNumber}") - @ApiOperation(value = "Get account details", notes = "Find account details by account number") - @ApiResponses(value = { @ApiResponse(code = 200, message = "Success"), - @ApiResponse(code = 400, message = "Bad Request"), - @ApiResponse(code = 500, message = "Internal Server Error") }) + @Operation(summary = "Get account details", description = "Find account details by account number") + @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Success"), + @ApiResponse(responseCode = "400", description = "Bad Request"), + @ApiResponse(responseCode = "500", description = "Internal Server Error") }) public ResponseEntity getByAccountNumber(@PathVariable Long accountNumber) { @@ -42,10 +42,10 @@ public ResponseEntity getByAccountNumber(@PathVariable Long accountNumbe } @PostMapping(path = "/add/{customerNumber}") - @ApiOperation(value = "Add a new account", notes = "Create an new account for existing customer.") - @ApiResponses(value = { @ApiResponse(code = 200, message = "Success"), - @ApiResponse(code = 400, message = "Bad Request"), - @ApiResponse(code = 500, message = "Internal Server Error") }) + @Operation(summary = "Add a new account", description = "Create an new account for existing customer.") + @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Success"), + @ApiResponse(responseCode = "400", description = "Bad Request"), + @ApiResponse(responseCode = "500", description = "Internal Server Error") }) public ResponseEntity addNewAccount(@RequestBody AccountInformation accountInformation, @PathVariable Long customerNumber) { @@ -54,10 +54,10 @@ public ResponseEntity addNewAccount(@RequestBody AccountInformation acco } @PutMapping(path = "/transfer/{customerNumber}") - @ApiOperation(value = "Transfer funds between accounts", notes = "Transfer funds between accounts.") - @ApiResponses(value = { @ApiResponse(code = 200, message = "Success", response = Object.class), - @ApiResponse(code = 400, message = "Bad Request"), - @ApiResponse(code = 500, message = "Internal Server Error") }) + @Operation(summary = "Transfer funds between accounts", description = "Transfer funds between accounts.") + @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Success"), + @ApiResponse(responseCode = "400", description = "Bad Request"), + @ApiResponse(responseCode = "500", description = "Internal Server Error") }) public ResponseEntity transferDetails(@RequestBody TransferDetails transferDetails, @PathVariable Long customerNumber) { @@ -66,10 +66,10 @@ public ResponseEntity transferDetails(@RequestBody TransferDetails trans } @GetMapping(path = "/transactions/{accountNumber}") - @ApiOperation(value = "Get all transactions", notes = "Get all Transactions by account number") - @ApiResponses(value = { @ApiResponse(code = 200, message = "Success"), - @ApiResponse(code = 400, message = "Bad Request"), - @ApiResponse(code = 500, message = "Internal Server Error") }) + @Operation(summary = "Get all transactions", description = "Get all Transactions by account number") + @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Success"), + @ApiResponse(responseCode = "400", description = "Bad Request"), + @ApiResponse(responseCode = "500", description = "Internal Server Error") }) public List getTransactionByAccountNumber(@PathVariable Long accountNumber) { diff --git a/src/main/java/com/coding/exercise/bankapp/controller/CustomerController.java b/src/main/java/com/coding/exercise/bankapp/controller/CustomerController.java index 58e9044..d605fe9 100644 --- a/src/main/java/com/coding/exercise/bankapp/controller/CustomerController.java +++ b/src/main/java/com/coding/exercise/bankapp/controller/CustomerController.java @@ -16,24 +16,24 @@ import com.coding.exercise.bankapp.domain.CustomerDetails; import com.coding.exercise.bankapp.service.BankingServiceImpl; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; @RestController @RequestMapping("customers") -@Api(tags = { "Customer REST endpoints" }) +@Tag(name = "Customer REST endpoints") public class CustomerController { @Autowired private BankingServiceImpl bankingService; @GetMapping(path = "/all") - @ApiOperation(value = "Find all customers", notes = "Gets details of all the customers") - @ApiResponses(value = { @ApiResponse(code = 200, message = "Success"), - @ApiResponse(code = 400, message = "Bad Request"), - @ApiResponse(code = 500, message = "Internal Server Error") }) + @Operation(summary = "Find all customers", description = "Gets details of all the customers") + @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Success"), + @ApiResponse(responseCode = "400", description = "Bad Request"), + @ApiResponse(responseCode = "500", description = "Internal Server Error") }) public List getAllCustomers() { @@ -41,10 +41,10 @@ public List getAllCustomers() { } @PostMapping(path = "/add") - @ApiOperation(value = "Add a Customer", notes = "Add customer and create an account") - @ApiResponses(value = { @ApiResponse(code = 200, message = "Success"), - @ApiResponse(code = 400, message = "Bad Request"), - @ApiResponse(code = 500, message = "Internal Server Error") }) + @Operation(summary = "Add a Customer", description = "Add customer and create an account") + @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Success"), + @ApiResponse(responseCode = "400", description = "Bad Request"), + @ApiResponse(responseCode = "500", description = "Internal Server Error") }) public ResponseEntity addCustomer(@RequestBody CustomerDetails customer) { @@ -52,11 +52,11 @@ public ResponseEntity addCustomer(@RequestBody CustomerDetails customer) } @GetMapping(path = "/{customerNumber}") - @ApiOperation(value = "Get customer details", notes = "Get Customer details by customer number.") + @Operation(summary = "Get customer details", description = "Get Customer details by customer number.") @ApiResponses(value = { - @ApiResponse(code = 200, message = "Success", response = CustomerDetails.class, responseContainer = "Object"), - @ApiResponse(code = 400, message = "Bad Request"), - @ApiResponse(code = 500, message = "Internal Server Error") }) + @ApiResponse(responseCode = "200", description = "Success"), + @ApiResponse(responseCode = "400", description = "Bad Request"), + @ApiResponse(responseCode = "500", description = "Internal Server Error") }) public CustomerDetails getCustomer(@PathVariable Long customerNumber) { @@ -64,10 +64,10 @@ public CustomerDetails getCustomer(@PathVariable Long customerNumber) { } @PutMapping(path = "/{customerNumber}") - @ApiOperation(value = "Update customer", notes = "Update customer and any other account information associated with him.") - @ApiResponses(value = { @ApiResponse(code = 200, message = "Success", response = Object.class), - @ApiResponse(code = 400, message = "Bad Request"), - @ApiResponse(code = 500, message = "Internal Server Error") }) + @Operation(summary = "Update customer", description = "Update customer and any other account information associated with him.") + @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Success"), + @ApiResponse(responseCode = "400", description = "Bad Request"), + @ApiResponse(responseCode = "500", description = "Internal Server Error") }) public ResponseEntity updateCustomer(@RequestBody CustomerDetails customerDetails, @PathVariable Long customerNumber) { @@ -76,10 +76,10 @@ public ResponseEntity updateCustomer(@RequestBody CustomerDetails custom } @DeleteMapping(path = "/{customerNumber}") - @ApiOperation(value = "Delete customer and related accounts", notes = "Delete customer and all accounts associated with him.") - @ApiResponses(value = { @ApiResponse(code = 200, message = "Success", response = Object.class), - @ApiResponse(code = 400, message = "Bad Request"), - @ApiResponse(code = 500, message = "Internal Server Error") }) + @Operation(summary = "Delete customer and related accounts", description = "Delete customer and all accounts associated with him.") + @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Success"), + @ApiResponse(responseCode = "400", description = "Bad Request"), + @ApiResponse(responseCode = "500", description = "Internal Server Error") }) public ResponseEntity deleteCustomer(@PathVariable Long customerNumber) { diff --git a/src/test/java/com/coding/exercise/bankapp/BankingApplicationTests.java b/src/test/java/com/coding/exercise/bankapp/BankingApplicationTests.java index 803c91d..6b76be1 100644 --- a/src/test/java/com/coding/exercise/bankapp/BankingApplicationTests.java +++ b/src/test/java/com/coding/exercise/bankapp/BankingApplicationTests.java @@ -1,11 +1,8 @@ package com.coding.exercise.bankapp; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; -@RunWith(SpringRunner.class) @SpringBootTest public class BankingApplicationTests {