A production-ready RESTful API for an e-commerce platform built with Spring Boot 3, following Modular Monolith architecture with Port & Adapter pattern β designed for easy migration to microservices.
- Tech Stack
- Architecture
- Modules
- Features
- Getting Started
- API Documentation
- Testing
- Project Structure
| Category | Technology |
|---|---|
| Framework | Spring Boot 3.5, Spring Security, Spring Data JPA |
| Language | Java 21 |
| Database | PostgreSQL 16 |
| Cache | Redis 7 |
| Authentication | JWT (Access + Refresh Token) |
| Payment | VNPay |
| Image Upload | Cloudinary |
| JavaMailSender + MailHog (dev) | |
| Real-time | Server-Sent Events (SSE) |
| Documentation | Swagger / OpenAPI 3 |
| Testing | JUnit 5, Testcontainers, k6 |
| Build | Maven |
The application is structured as a Modular Monolith β each business domain is an independent module with clear boundaries, communicating through defined interfaces (Ports).
βββββββββββββββββββββββββββββββββββββββββββββββ
β API Layer β
β (Controllers + Swagger) β
ββββββββββββ¬βββββββββββ¬ββββββββββββ¬ββββββββββββ€
β User β Catalog β Order β Payment β
β Module β Module β Module β Module β
ββββββββββββ΄βββββββββββ΄ββββββββββββ΄ββββββββββββ€
β Port & Adapter β
β (Inter-module communication via β
β interfaces, not direct calls) β
βββββββββββββββββββββββββββββββββββββββββββββββ€
β Spring Event Bus β
β (Async: OrderCreated β ReserveStock) β
ββββββββββββββββββββ¬βββββββββββββββββββββββββββ€
β PostgreSQL β Redis Cache β
ββββββββββββββββββββ΄βββββββββββββββββββββββββββ
- Port & Adapter β modules communicate through interfaces, never direct class calls
- Spring Events β async domain events replace tight coupling (e.g.,
OrderCreatedEventβ Inventory reserves stock) - Optimistic Locking β prevents overselling without pessimistic locks
- Idempotency Keys β duplicate order requests are safely ignored
- Snapshot Pattern β order items store price/name at time of purchase
Each module follows the same internal structure as a microservice:
Handler (Event) β Service β Port Interface
Controller (HTTP) β Service β Port Interface
Migrating to microservices only requires:
- Replacing
@EventListenerwith@KafkaListener - Replacing Port JPA implementations with Feign Clients
- No changes to Service or Handler layer
| Module | Responsibility |
|---|---|
| user | Auth (JWT), profile, address, wishlist |
| catalog | Products, categories, variants, image upload |
| inventory | Stock management, optimistic locking |
| order | Cart, order lifecycle, vouchers |
| payment | COD & VNPay integration |
| review | Product reviews & ratings |
| notification | Real-time SSE + email notifications |
- Register / Login with JWT (Access + Refresh Token)
- Refresh token rotation β old token revoked on refresh
- Logout β revokes refresh token
- Change password β revokes all sessions
- Forgot password β email with reset link (15-min expiry via Redis)
- Reset password
- User profile management
- Multiple shipping addresses
- Product listing with filtering & pagination
- Category management
- Product variants (size, color, etc.)
- Image upload via Cloudinary
- Real-time stock tracking
- Optimistic Locking β concurrent purchase protection
- Reserve β Commit / Release flow
- Persistent cart (1 cart per user)
- Place order from cart
- Voucher / discount codes
- Dynamic shipping fee calculation
- Order status history (full audit trail)
- Order cancellation
- Auto-cancel on payment timeout (15 minutes)
- COD β auto-confirms order immediately
- VNPay β redirect flow with callback verification
- Idempotency β duplicate payments safely rejected
- Payment event audit log
- Real-time SSE β instant order status push to browser
- Email β order status change notifications
- MailHog for local email testing
- User management (ban/unban)
- Product & category CRUD
- Inventory management
- Order management & status updates
- Voucher management
- Sales dashboard
- Java 21+
- Maven 3.9+
- Docker & Docker Compose
git clone https://github.com/Tran-Nguyen-26/ecommerce.git
cd ecommerce
# Start PostgreSQL, Redis, MailHog
docker-compose up -dCopy and update environment variables (or use defaults for local dev):
# application.yml defaults work out of the box for local dev
# PostgreSQL: localhost:5433
# Redis: localhost:6380
# MailHog: localhost:1025 (SMTP), localhost:8025 (UI)./mvnw spring-boot:run| Service | URL |
|---|---|
| API | http://localhost:8080 |
| Swagger UI | http://localhost:8080/swagger-ui.html |
| MailHog UI | http://localhost:8025 |
| Health Check | http://localhost:8080/actuator/health |
Full API docs available at http://localhost:8080/swagger-ui.html
src/main/java/com/ttn/ecommerce/
βββ infrastructure/
β βββ config/ # Security, CORS, Swagger
β βββ email/ # EmailService
βββ modules/
β βββ catalog/
β β βββ api/ # Controllers
β β βββ application/ # Services, DTOs, Ports
β β βββ domain/ # Entities
β β βββ infrastructure/ # JPA Repositories, Port impls
β βββ inventory/
β βββ notification/
β βββ order/
β βββ payment/
β βββ review/
β βββ user/
βββ shared/
βββ event/ # Domain events + EventPublisherPort
βββ exception/ # GlobalExceptionHandler, ErrorCode
βββ response/ # ApiResponse wrapper
| Service | Container | Port |
|---|---|---|
| PostgreSQL | ecommerce-db | 5433:5432 |
| Redis | ecommerce-redis | 6380:6379 |
| MailHog | ecommerce-mail | 1025 (SMTP), 8025 (UI) |
MIT