Skip to content

A production-grade Fintech Backend Simulation built with Spring Boot 4. Features Stateful Authentication (Redis), ACID Transactions, and Concurrency Control (Pessimistic Locking) to prevent race conditions.

Notifications You must be signed in to change notification settings

kaantopcuw/JCoin

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

J-Coin Wallet (Fintech Backend Simulation)

J-Coin Wallet is a high-security backend simulation for a banking/wallet application. It is designed to demonstrate production-grade architectural patterns, focusing on data integrity, concurrency control, and secure session management.

Unlike standard CRUD applications, this project implements strict ACID compliance and Pessimistic Locking strategies to prevent race conditions (double-spending) and deadlocks during financial transactions.

🛠 Tech Stack

  • Language: Java 25
  • Framework: Spring Boot 4.0.1
  • Database: PostgreSQL (Relational Data)
  • Cache & Session: Redis (In-Memory Data Structure Store)
  • Security: Spring Security (Session Management)
  • Containerization: Docker & Docker Compose

🏗 Architecture & Design Principles

This project was built with a "Defense in Depth" and "Data Integrity First" mindset. Below are the key engineering decisions:

1. Security: Stateful Session Management (Redis)

Instead of standard stateless JWTs (which are hard to revoke immediately), we implemented a Stateful Auth pattern using Spring Session and Redis.

  • Reference Token Pattern: The client receives a random Session ID (via Cookie), while the actual user data is stored securely in Redis.
  • Revocation: This allows for instant account suspension or logout, essential for banking apps.
  • HttpOnly Cookies: The session ID is stored in an HttpOnly cookie, making it inaccessible to client-side JavaScript, effectively neutralizing XSS (Cross-Site Scripting) attacks.
  • Strict Security Config: Unauthenticated requests are blocked at the filter chain level with a custom AuthenticationEntryPoint that returns proper JSON errors instead of HTML.

2. Concurrency Control (Preventing Race Conditions)

Financial transactions require strict synchronization.

  • Pessimistic Locking: We use SELECT ... FOR UPDATE (via JPA @Lock(LockModeType.PESSIMISTIC_WRITE)) when fetching wallets during a transfer. This prevents two concurrent threads from reading the same balance before one has finished writing, eliminating the Double Spending risk.
  • Deadlock Prevention: To avoid database deadlocks when two users transfer money to each other simultaneously, we implemented Ordered Locking. Resources (Wallets) are always locked in a specific order (based on ID), ensuring that circular dependencies cannot occur.

3. Modular Monolith Structure

The codebase is organized by domain features rather than technical layers:

  • core: Shared entities, exceptions, and security configurations.
  • modules.auth: Registration and authentication logic.
  • modules.wallet: Wallet management, deposits, transfers, and transaction history.

🚀 Getting Started

Prerequisites

  • Java 25 or higher
  • Docker & Docker Compose
  • Maven

Installation

  1. Clone the repository:
git clone https://github.com/your-username/j-coin-wallet.git
cd j-coin-wallet
  1. Start Infrastructure (Postgres & Redis): We use Docker Compose to spin up the required databases.
docker-compose up -d
  1. Run the Application:
mvn spring-boot:run

The application will start on http://localhost:8080.


📖 API Documentation

The API follows RESTful standards. All responses are in JSON format.

🔐 Authentication Module

1. Register a New User

  • Endpoint: POST /api/auth/register
  • Description: Creates a new user with ROLE_USER.
  • Body:
{
    "name": "John Doe",
    "email": "[email protected]",
    "password": "securePassword123"
}
  • Response (201 Created):
"Registration successful"

2. Login

  • Endpoint: POST /api/auth/login
  • Description: Authenticates the user and sets an HttpOnly SESSION cookie.
  • Body:
{
    "email": "[email protected]",
    "password": "securePassword123"
}
  • Response (200 OK):
{
    "message": "Login successful",
    "userId": 1,
    "name": "John Doe"
}

Note: Check your browser or Postman cookies to see the SESSION cookie.


💰 Wallet Module (Requires Auth)

1. Create a Wallet

  • Endpoint: POST /api/wallets
  • Body:
{
    "currency": "TRY"
}
  • Response (201 Created):
{
    "id": 1,
    "currency": "TRY",
    "balance": 0
}

2. List My Wallets

  • Endpoint: GET /api/wallets
  • Response (200 OK):
[
    {
        "id": 1,
        "currency": "TRY",
        "balance": 5000.00
    },
    {
        "id": 2,
        "currency": "USD",
        "balance": 100.00
    }
]

3. Deposit Money

  • Endpoint: POST /api/wallets/deposit
  • Description: Adds funds to a specific wallet.
  • Body:
{
    "walletId": 1,
    "amount": 1000.50
}

4. Transfer Money (The Critical Part)

  • Endpoint: POST /api/wallets/transfer
  • Description: Securely transfers money between two wallets using ACID transactions and Pessimistic Locking.
  • Body:
{
    "fromWalletId": 1,
    "toWalletId": 2,
    "amount": 250.00,
    "description": "Debt payment"
}
  • Response (200 OK):
"Transfer successful"

5. Transaction History (Pagination)

  • Endpoint: GET /api/wallets/{walletId}/transactions?page=0&size=10
  • Description: Fetches incoming and outgoing transactions for a specific wallet.
  • Response (200 OK):
{
    "content": [
        {
            "referenceNumber": "c89d-...",
            "amount": 250.00,
            "type": "TRANSFER",
            "date": "2024-01-04T15:30:00",
            "description": "Debt payment",
            "fromWalletId": 1,
            "toWalletId": 2
        }
    ],
    "pageable": {  },
    "totalPages": 1,
    "totalElements": 1
}

🛡️ Error Handling

The application features a GlobalExceptionHandler and a Custom AuthenticationEntryPoint.

  • 401 Unauthorized: Invalid email/password or missing session.
{
    "error": "Unauthorized",
    "message": "Please login. Your session might be expired.",
    "path": "/api/wallets"
}
  • 400 Bad Request: Validation errors (e.g., negative amount, invalid email).
  • 500 Internal Server Error: Unexpected system failures (e.g., Database connection lost).

👨‍💻 Author

Developed as a comprehensive study on Secure Java Backend Architecture.

About

A production-grade Fintech Backend Simulation built with Spring Boot 4. Features Stateful Authentication (Redis), ACID Transactions, and Concurrency Control (Pessimistic Locking) to prevent race conditions.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages