Micronaut is a powerful framework for building microservices and REST APIs in Java. In this tutorial, we will be Building REST API in Micronaut for a banking application using Micronaut and Java 21. We will cover everything step-by-step so even beginners can follow along.
Project Overview
We will build a small banking API that allows us to:
- Create a bank account
- View account details
- Deposit money
- Withdraw money
Package structure: com.kscodes.banking
Prerequisites
- Java 21 installed
- Micronaut CLI installed (optional but recommended)
- VS Code (or any IDE)
- Maven
Step 1: Create a Micronaut Project
Using Micronaut CLI:
mn create-app com.kscodes.banking --java-version 21 --build maven
Or use Micronaut Launch and download the generated project with Maven as the build tool.
Open the project in VS Code.
Step 2: Define the Domain Model
Create a new file Account.java in:
src/main/java/com/kscodes/banking/model/
package com.kscodes.banking.model;
import java.math.BigDecimal;
import java.util.UUID;
public class Account {
private UUID accountId;
private String accountHolder;
private BigDecimal balance;
public Account(String accountHolder) {
this.accountId = UUID.randomUUID();
this.accountHolder = accountHolder;
this.balance = BigDecimal.ZERO;
}
public UUID getAccountId() { return accountId; }
public String getAccountHolder() { return accountHolder; }
public BigDecimal getBalance() { return balance; }
public void deposit(BigDecimal amount) {
balance = balance.add(amount);
}
public void withdraw(BigDecimal amount) {
balance = balance.subtract(amount);
}
}
Step 3: Create a Simple Service
Create AccountService.java in:
src/main/java/com/kscodes/banking/service/
package com.kscodes.banking.service;
import com.kscodes.banking.model.Account;
import jakarta.inject.Singleton;
import java.math.BigDecimal;
import java.util.*;
@Singleton
public class AccountService {
private final Map accounts = new HashMap<>();
public Account createAccount(String accountHolder) {
Account account = new Account(accountHolder);
accounts.put(account.getAccountId(), account);
return account;
}
public Optional getAccount(UUID accountId) {
return Optional.ofNullable(accounts.get(accountId));
}
public Optional deposit(UUID accountId, BigDecimal amount) {
Account account = accounts.get(accountId);
if (account != null) {
account.deposit(amount);
return Optional.of(account);
}
return Optional.empty();
}
public Optional withdraw(UUID accountId, BigDecimal amount) {
Account account = accounts.get(accountId);
if (account != null) {
account.withdraw(amount);
return Optional.of(account);
}
return Optional.empty();
}
}
Step 4: Create REST Controller
Create AccountController.java in:
src/main/java/com/kscodes/banking/controller/
package com.kscodes.banking.controller;
import com.kscodes.banking.model.Account;
import com.kscodes.banking.service.AccountService;
import io.micronaut.http.HttpResponse;
import io.micronaut.http.annotation.*;
import jakarta.inject.Inject;
import java.math.BigDecimal;
import java.util.Optional;
import java.util.UUID;
@Controller("/accounts")
public class AccountController {
@Inject
AccountService accountService;
@Post("/")
public Account createAccount(@Body String accountHolder) {
return accountService.createAccount(accountHolder);
}
@Get("/{accountId}")
public HttpResponse getAccount(UUID accountId) {
return accountService.getAccount(accountId)
.map(HttpResponse::ok)
.orElse(HttpResponse.notFound());
}
@Post("/{accountId}/deposit")
public HttpResponse deposit(UUID accountId, @Body BigDecimal amount) {
return accountService.deposit(accountId, amount)
.map(HttpResponse::ok)
.orElse(HttpResponse.notFound());
}
@Post("/{accountId}/withdraw")
public HttpResponse withdraw(UUID accountId, @Body BigDecimal amount) {
return accountService.withdraw(accountId, amount)
.map(HttpResponse::ok)
.orElse(HttpResponse.notFound());
}
}
Step 5: Run and Test
Build and run the application:
mvnw mn:run

Example API calls:
- Create Account:
curl -X POST http://localhost:8080/accounts -d "John Doe"
- Deposit Money:
curl -X POST http://localhost:8080/accounts/{accountId}/deposit -d 500.00
- Withdraw Money:
curl -X POST http://localhost:8080/accounts/{accountId}/withdraw -d 200.00
- Get Account Info:
curl http://localhost:8080/accounts/{accountId}
Step 6: Using Virtual Threads (Java 21 Feature)
In application.yml, enable virtual threads:
micronaut:
executors:
io:
type: virtual
This allows your Micronaut app to scale better with Java 21.
Summary
- We created a simple banking REST API using Micronaut.
- Implemented account creation, deposit, withdrawal, and fetching account info.
- Used Java 21 virtual threads.
- Simple in-memory storage (can be extended with a database).
Stay tuned for future posts where we will add database support, validations, exception handling, and more enterprise-ready features!