This project implements a robust, distributed architecture for an Order Management System, built with Java 21 and Spring Boot 3. It adopts a microservices approach, utilizing an Auth Gateway pattern to handle security at the edge.
A high-performance, distributed ecosystem designed for secure order management. This project features a robust API Gateway using a manual WebClient proxy pattern to ensure centralized authentication and seamless service orchestration.
Key architectural highlights include:
- Zero-Trust Edge Security: Stateless JWT authentication and manual proxy routing via Spring WebFlux
WebClient. - Modern Persistence: Powered by PostgreSQL 17, utilizing time-ordered
UUID v7for optimal B-Tree index performance and anti-fragmentation. - Automated Image Publish: Pipeline orchestrated with GitHub Actions for testing and publish JVM images.
- Javadoc + TestReports + Coverage Tests Reports: https://vitorhugo-java.github.io/distributed-gateway-order-system/
The system is architected as a set of decoupled microservices that communicate over a private network, ensuring data integrity and security.
This project is fully containerized for a one-click deployment experience.
- Docker and Docker Compose
- Java 21 (for local development)
- Clone the repository:
git clone https://github.com/your-user/distributed-order-orchestrator.git
cd distributed-order-orchestrator- Start the full stack:
docker-compose up --build- Access the services:
- Gateway (Entry Point): http://localhost:8080
- Direct Orders API: http://localhost:8081 (internal use recommended)
- Database: localhost:5432
- Core: Java 21, Spring Boot 3.3.6
- Security: Spring Security, JWT (JSON Web Token)
- Networking: Spring WebFlux (WebClient) for reactive proxying
- Persistence: Spring Data JPA, Hibernate 7, Flyway Migrations
- Databases: PostgreSQL (Production), H2 (Tests/Dev Profile)
- DevOps: Docker, multi-stage Dockerfiles, Docker Compose, GitHub Actions
- Documentation: SpringDoc OpenAPI (Swagger UI)
We implement stateless authentication using JWT.
- Login: POST /auth/login returns a token
- Authorization: Use Authorization: Bearer
- Validation: Gateway validates signature and expiration (1h)
- POST /auth/login
- ANY /api/orders/**
- GET /api/orders
- POST /api/orders
- GET /api/orders/{id}
- DELETE /api/orders/{id}
curl -X POST "http://localhost:8080/auth/login" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"username": "admin",
"password": "admin123"
}'Response:
{
"token": "eyJhbGciOiJIUzI1NiJ9.eyJ...",
"type": "Bearer",
"expiresIn": 3600000
}curl -X POST "http://localhost:8080/api/orders" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "Authorization: Bearer <TOKEN>" \
-d '{
"customerName": "README Demo",
"customerEmail": "readme.demo@example.com",
"orderDate": "2026-04-29T23:24:54",
"status": "PENDING",
"totalAmount": 149.90
}'Response:
{
"id": "0a60001a-9ddb-1157-819d-db8f4bab0004",
"customerName": "README Demo",
"customerEmail": "readme.demo@example.com",
"orderDate": "2026-04-29T23:24:54",
"status": "PENDING",
"totalAmount": 149.9,
"items": []
}curl -X GET "http://localhost:8080/api/orders" \
-H "Accept: application/json" \
-H "Authorization: Bearer <TOKEN>"Response:
{
"content": [
{
"id": "0a60001a-9ddb-1157-819d-db8f4bab0004",
"customerName": "README Demo",
"customerEmail": "readme.demo@example.com",
"orderDate": "2026-04-29T23:24:54",
"status": "PENDING",
"totalAmount": 149.9,
"items": []
}
],
"empty": false,
"first": true,
"last": true,
"number": 0,
"numberOfElements": 1,
"pageable": {
"offset": 0,
"pageNumber": 0,
"pageSize": 20,
"paged": true,
"sort": {
"empty": true,
"sorted": false,
"unsorted": true
},
"unpaged": false
},
"size": 20,
"sort": {
"empty": true,
"sorted": false,
"unsorted": true
},
"totalElements": 1,
"totalPages": 1
}curl -X GET "http://localhost:8080/api/orders/0a60001a-9ddb-1157-819d-db8f4bab0004" \
-H "Accept: application/json" \
-H "Authorization: Bearer <TOKEN>"Response:
{
"id": "0a60001a-9ddb-1157-819d-db8f4bab0004",
"customerName": "README Demo",
"customerEmail": "readme.demo@example.com",
"orderDate": "2026-04-29T23:24:54",
"status": "PENDING",
"totalAmount": 149.9,
"items": []
}curl -X POST "http://localhost:8080/api/orders/0a60001a-9ddb-1157-819d-db8f4bab0004/items" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "Authorization: Bearer <TOKEN>" \
-d '{
"productName": "Mechanical Keyboard",
"quantity": 1,
"unitPrice": 149.90
}'Response:
{
"id": null,
"productName": "Mechanical Keyboard",
"quantity": 1,
"unitPrice": 149.9,
"subtotal": 149.9
}curl -X GET "http://localhost:8080/api/orders/0a60001a-9ddb-1157-819d-db8f4bab0004/items" \
-H "Accept: application/json" \
-H "Authorization: Bearer <TOKEN>"Response:
[
{
"id": "0a60001a-9ddb-1157-819d-db8f4c0f0005",
"productName": "Mechanical Keyboard",
"quantity": 1,
"unitPrice": 149.9,
"subtotal": 149.9
}
]- Username: admin
- Password: admin123
- Manual Proxying (instead of use Spring Cloud Gateway): WebClient used for fine-grained control over headers and error handling
- Database per Service: isolated databases to enforce shared-nothing architecture
- Multi-Stage Build: optimized Docker images with reduced size and attack surface
- JWT for Stateless Auth: eliminates session management and scales horizontally without sticky sessions
- UUID v7 for IDs orders-crud: time-ordered, optimized for B-Tree indexes in PostgreSQL, reduces fragmentation and avoid lock. The cons for using UUID is that it use more storage space than a traditional auto-incrementing integer, and use a little more CPU (~30β45 ns) than integer autoincrement, and it can be less performant for certain queries due to its larger size. However, the benefits of global uniqueness and reduced fragmentation often outweigh these drawbacks in distributed systems.
- Qodana: Static code analysis to ensure code quality and maintainability.
- images-multi-module.yml: Build and publish JVM images to GitHub Container Registry (GHCR) for all microservices.
- deploy-docs.yml: Deploy Docs and Coverage Reports to GitHub Pages.
