A Beginner's Guide to Creating a Simple Bank Service with REST Endpoints.
You've built applications that run in the terminal. Now, let's create a backend service that can be accessed over the internet. This is the foundation of modern web applications.
In this tutorial, we will use **Java Spring Boot**, a powerful framework that makes building robust web services incredibly fast and easy. We will build a simple banking API that can show an account balance, process deposits, and handle withdrawals.
To create a simple REST API with three endpoints:
The easiest way to start a new Spring Boot project is by using the **Spring Initializr**.
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; }
}
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!
}
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();
}
}
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());
}
}
}
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
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
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`
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.