Build a Banking API with Java Spring Boot ☕

A Beginner's Guide to Creating a Simple Bank Service with REST Endpoints.

Step 0: Prerequisites & Goal 🎯
Project Goal

To create a simple REST API with three endpoints:

  • `GET /api/account` - Fetches the current balance.
  • `POST /api/account/deposit` - Adds money to the account.
  • `POST /api/account/withdraw` - Removes money from the account.
What You'll Need
  • Java Development Kit (JDK): Version 17 or newer is recommended.
  • An IDE: IntelliJ IDEA, Eclipse, or Visual Studio Code with Java extensions.
  • Maven or Gradle: A build tool, usually integrated into your IDE.
Step 1: Setting Up the Spring Boot Project 🌱

The easiest way to start a new Spring Boot project is by using the **Spring Initializr**.

  1. Go to the website: start.spring.io
  2. Fill in the project metadata as shown:
    • Project: Maven
    • Language: Java
    • Spring Boot: A recent stable version (e.g., 3.3.x)
    • Group: `com.example`
    • Artifact: `simple-bank`
    • Packaging: Jar
    • Java: 17
  3. In the "Dependencies" section on the right, click "Add Dependencies" and add the following:
    • Spring Web: For building RESTful web applications.
    • Spring Data JPA: For database interaction.
    • H2 Database: An in-memory database, perfect for development.
  4. Click the "Generate" button. A ZIP file will be downloaded.
  5. Unzip the file and open the project folder in your IDE.
Step 2: The Data Model (The `Account` Entity) 🏛️

An **Entity** is a Java class that represents a table in our database. We need one to store our account information.

Inside `src/main/java/com/example/simplebank`, create a new Java class named `Account.java`.

package com.example.simplebank;

import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;

@Entity // Tells JPA this class is a database entity
public class Account {

    @Id // Marks this field as the primary key
    @GeneratedValue(strategy = GenerationType.IDENTITY) // Auto-increments the ID
    private Long id;

    private double balance;

    // Constructors, Getters, and Setters
    public Account() {}

    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }

    public double getBalance() { return balance; }
    public void setBalance(double balance) { this.balance = balance; }
}
Step 3: The Repository (The Data Access Layer) 🗄️

A **Repository** is an interface that handles all the database operations (like find, save, delete) for an entity. The magic of Spring Data JPA is that we only need to define the interface; Spring provides the implementation automatically!

Create a new Java interface named `AccountRepository.java`.

package com.example.simplebank;

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

@Repository
public interface AccountRepository extends JpaRepository<Account, Long> {
    // By extending JpaRepository, we get methods like save(), findById(), findAll(), etc.
    // for our Account entity, without writing any code!
}
Step 4: The Service (The Business Logic) ⚙️

A **Service** class holds the core logic of our application. It sits between the web controller and the data repository.

Create a new Java class named `AccountService.java`.

package com.example.simplebank;

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

@Service
public class AccountService {

    @Autowired // Asks Spring to provide an instance of AccountRepository
    private AccountRepository accountRepository;

    // Create a default account with a starting balance when the application starts
    @PostConstruct
    private void init() {
        Account account = new Account();
        account.setBalance(100.00); // Initial balance
        accountRepository.save(account);
    }
    
    public Account deposit(double amount) {
        // For simplicity, we'll always use the first account (ID 1)
        Account account = accountRepository.findById(1L).orElseThrow(() -> new RuntimeException("Account not found"));
        account.setBalance(account.getBalance() + amount);
        return accountRepository.save(account);
    }

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

    public double getBalance() {
        Account account = accountRepository.findById(1L).orElseThrow(() -> new RuntimeException("Account not found"));
        return account.getBalance();
    }
}
Key Concept: Dependency Injection. The `@Autowired` annotation is a core feature of Spring. Instead of us creating an `AccountRepository` object manually, we just declare it, and Spring "injects" a ready-to-use instance for us.
Step 5: The Controller (The API Endpoints) 🔌

A **Controller** is a class that listens for incoming HTTP requests and directs them to the right service method. This is how we expose our application to the outside world.

Create a new Java class named `AccountController.java`.

package com.example.simplebank;

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

@RestController // Marks this as a controller for REST APIs
@RequestMapping("/api/account") // All endpoints in this class start with /api/account
public class AccountController {

    @Autowired
    private AccountService accountService;

    @GetMapping
    public ResponseEntity<Double> getBalance() {
        return ResponseEntity.ok(accountService.getBalance());
    }

    @PostMapping("/deposit")
    public ResponseEntity<Account> deposit(@RequestParam Double amount) {
        return ResponseEntity.ok(accountService.deposit(amount));
    }

    @PostMapping("/withdraw")
    public ResponseEntity<?> withdraw(@RequestParam Double amount) {
        try {
            return ResponseEntity.ok(accountService.withdraw(amount));
        } catch (RuntimeException e) {
            // Return a 400 Bad Request status with the error message
            return ResponseEntity.badRequest().body(e.getMessage());
        }
    }
}
Step 6: Configure & Run The Application! 🚀

We need to tell Spring Boot how to access our H2 in-memory database and enable its web console.

Open the file `src/main/resources/application.properties` and add the following lines:

# Enable H2 web console
spring.h2.console.enabled=true
# Set the path for the console
spring.h2.console.path=/h2-console

# Datasource Properties for H2
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
Running the Application

Find the file `SimpleBankApplication.java` in your main package. It will have a `main` method. You can run the application by simply running this file from your IDE.

Alternatively, open a terminal in the project's root directory and run:

./mvnw spring-boot:run
Testing the API

Once the server is running (usually on port 8080), you can test your endpoints using a tool like `curl` or Postman.

1. Get Balance:

curl http://localhost:8080/api/account

Expected Output: `100.0`

2. Make a Deposit:

curl -X POST "http://localhost:8080/api/account/deposit?amount=50.50"

Expected Output: A JSON object with the new balance of `150.5`

3. Make a Withdrawal:

curl -X POST "http://localhost:8080/api/account/withdraw?amount=20"

Expected Output: A JSON object with the new balance of `130.5`

4. Try to Withdraw too much:

curl -X POST "http://localhost:8080/api/account/withdraw?amount=500"

Expected Output: `Insufficient funds`

Congratulations! You've Built a Java REST API! 🎉

You have successfully created a fully functional backend service with Java Spring Boot. You learned how Spring's powerful components work together:


This project is the starting point for building much larger and more complex applications. You can now explore adding more features like multiple accounts, user authentication, and transaction histories.