Banking Application using Spring Boot

In this tutorial, we will learn how to build REST APIs for a simple Banking application using Spring Boot, Spring Data JPA (Hibernate) and MySQL database.

We'll create a simple version of Banking App with basic functionalities: creating a bank account, fetching account details, and making a deposit/withdrawal.

1. Set up a Spring Boot project

Let's launch Spring Initializr and fill up the following project details: 

Project: Maven Project (or Gradle) 

Language: Java 

Packaging: Jar 

Java version: 17

Dependencies: Spring Web, Spring Data JPA, MySQL Driver, and Lombok

Download, extract the project and import in your favorite IDE.

2. Configure the MySQL database 

Let's open src/main/resources/application.properties file and add the MySQL configuration properties:

spring.datasource.url=jdbc:mysql://localhost:3306/banking_app
spring.datasource.username=root
spring.datasource.password=Mysql@123
spring.jpa.hibernate.ddl-auto=update

Make sure that you change the MySQL database username and password as per your MySQL installation on your machine.

The spring.jpa.hibernate.ddl-auto=update line ensures that tables and columns get automatically created or updated based on your JPA entities.

3. Create the Account entity

Let's create a Account JPA entity class and add the following code to it:
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
@Entity
public class Account {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String accountHolderName;
    private double balance;
}

Note that we are using Lombok annotations to reduce the boilerplate code.

Account Entity represents a bank account with properties like ID, account holder name, and balance. It uses JPA annotations to define the entity and its mapping to the database.

4. Create the JPA repository for the Account entity

Let's create AccountRepository interface that extends JpaRepository. Once AccountRepository interface extends JpaRepository then it will get the CRUD methods to perform CRUD database operations on Account entity.

import org.springframework.data.jpa.repository.JpaRepository;

public interface AccountRepository extends JpaRepository<Account, Long> {
}

5. Create the service class

The AccountService class contains the core business logic for the application:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Optional;

@Service
public class AccountService {

    @Autowired
    private AccountRepository accountRepository;

    public Account createAccount(Account account) {
        return accountRepository.save(account);
    }

    public Optional<Account> getAccount(Long id) {
        return accountRepository.findById(id);
    }

    public Account deposit(Long id, double amount) {
        Account account = getAccount(id).orElseThrow(() -> new RuntimeException("Account not found"));
        account.setBalance(account.getBalance() + amount);
        return accountRepository.save(account);
    }

    public Account withdraw(Long id, double amount) {
        Account account = getAccount(id).orElseThrow(() -> new RuntimeException("Account not found"));
        if (account.getBalance() < amount) {
            throw new RuntimeException("Insufficient funds");
        }
        account.setBalance(account.getBalance() - amount);
        return accountRepository.save(account);
    }
}

createAccount: Adds a new account to the database. 

getAccount: Retrieves an account's details by ID. 

deposit: Deposits a specified amount into an account. 

withdraw: Withdraws a specified amount from an account.

6. Create the REST controller

The AccountController class class exposes the business logic as RESTful API endpoints.

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.Map;

@RestController
@RequestMapping("/api/accounts")
public class AccountController {

    @Autowired
    private AccountService accountService;

    @PostMapping
    public Account createAccount(@RequestBody Account account) {
        return accountService.createAccount(account);
    }

    @GetMapping("/{id}")
    public Account getAccount(@PathVariable Long id) {
        return accountService.getAccount(id).orElseThrow(() -> new RuntimeException("Account not found"));
    }

    @PostMapping("/{id}/deposit")
    public Account deposit(@PathVariable Long id, @RequestBody Map<String, Double> request) {
        Double amount = request.get("amount");
        return accountService.deposit(id, amount);
    }

    @PostMapping("/{id}/withdraw")
    public Account withdraw(@PathVariable Long id, @RequestBody Map<String, Double> request) {
        Double amount = request.get("amount");
        return accountService.withdraw(id, amount);
    }
}

Run and Test Application

Navigate to the main application class (with @SpringBootApplication annotation) and run it as a Java application.

1. Create a new bank account: 

HTTP Method: POST 

URL: http://localhost:8080/api/accounts 

Sample Request Body:

{
    "accountHolderName": "Ramesh",
    "balance": 1000.00
}

2. Fetch the details of a specific account: 

HTTP Method: GET 

URL: http://localhost:8080/api/accounts/{id} (Replace {id} with the actual ID of the account you want to fetch.)

3. Deposit money into an account: 

HTTP Method: POST 
URL: http://localhost:8080/api/accounts/{id}/deposit (Replace {id} with the actual ID of the account you want to deposit money into.) 
Sample Request Body:
{
    "amount": 200.00
}

4. Withdraw money from an account: 

HTTP Method: POST 

URL: http://localhost:8080/api/accounts/{id}/withdraw (Replace {id} with the actual ID of the account you want to withdraw money from.) 

Sample Request Body:

{
    "amount": 150.00
}

Conclusion

In this tutorial, we learned basic implementation of a banking application's REST API, and there is always scope for improvements and adding more features. Before using this in any real-world application, consider integrating error handling, input validation, user authentication and authorization, security measures, etc.

Comments