An open API service indexing awesome lists of open source software.

https://github.com/rahul-ghadge/order-management-microservices

Production-ready Order Management System built with Spring Boot 3, Apache Kafka, Redis & PostgreSQL. Features event-driven microservices, stateless JWT auth, RBAC, per-service databases, Prometheus/Grafana observability, and full Docker Compose setup. One command to run everything.
https://github.com/rahul-ghadge/order-management-microservices

ddd docker event-driven java21 jwt kafka microservices open-api postgresql prafana prometheus redis spring-boot spring-cloud-gateway

Last synced: 25 days ago
JSON representation

Production-ready Order Management System built with Spring Boot 3, Apache Kafka, Redis & PostgreSQL. Features event-driven microservices, stateless JWT auth, RBAC, per-service databases, Prometheus/Grafana observability, and full Docker Compose setup. One command to run everything.

Awesome Lists containing this project

README

          

# πŸ—οΈ Spring Boot Order Management System β€” Microservices Architecture

> Demonstrating production-ready microservices
> with event-driven communication, distributed security, observability, and containerization.

> ### This is high level Architectural documentation.
> ### To deep dive into more technical stuff for these micro-services, [Detailed technical guide](https://github.com/rahul-ghadge/order-management-microservices/blob/main/DETAILED_TECHNICAL_GUIDE.md) is also present

---

## πŸ“ Architecture Overview

```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ CLIENT (Browser / Mobile) β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚ HTTPS
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ API GATEWAY :8080 β”‚
β”‚ JWT validation Β· Rate limiting Β· CORS β”‚
β”‚ Spring Cloud Gateway + Redis β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”˜
β”‚ β”‚ β”‚ β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β” β”Œβ”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β” β”Œβ”€β”€β–Όβ”€β”€β”€β”€β”€β”€β” β”Œβ”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ user-service β”‚ β”‚order-svc β”‚ β”‚pay-svc β”‚ β”‚notif-svc β”‚
β”‚ :8081 β”‚ β”‚ :8082 β”‚ β”‚ :8083 β”‚ β”‚ :8084 β”‚
β”‚ JWT issuance β”‚ β”‚ Order β”‚ β”‚Payment β”‚ β”‚Email dispatch β”‚
β”‚ Redis cache β”‚ β”‚ Kafka pub β”‚ β”‚Kafka pubβ”‚ β”‚Kafka consumer β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚ β”‚ β”‚
β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”
β”‚ PostgreSQL β”‚ β”‚PostgreSQL β”‚ β”‚PostgreSQL β”‚
β”‚ user_db β”‚ β”‚ order_db β”‚ β”‚payment_db β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Apache Kafka β”‚
β”‚ order.placed β”‚
β”‚ payment.processed β”‚
β”‚ order.status.changed β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Prometheus β”‚ β”‚ Grafana β”‚
β”‚ :9090 │──▢│ :3000 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```

---

## ✨ Key Features

| Category | Feature |
|---|---|
| **Architecture** | Event-driven microservices, Domain-Driven Design, clean package structure |
| **Security** | Stateless JWT (access + refresh tokens), token blacklisting via Redis, RBAC (`ROLE_USER`, `ROLE_ADMIN`), Spring Security 6 |
| **Messaging** | Apache Kafka with idempotent producer, consumer retry (3Γ— with back-off), DLT-ready |
| **Caching** | Redis for JWT blacklisting, user profiles (`@Cacheable`), order lookups, API Gateway rate limiting |
| **Persistence** | PostgreSQL per service (database-per-service pattern), JPA/Hibernate, UUID primary keys |
| **API** | RESTful APIs, Swagger/OpenAPI 3 on every service, standardised `ApiResponse` envelope |
| **Observability** | Micrometer + Prometheus + Grafana dashboards, Spring Boot Actuator on all services |
| **Containerisation** | Docker multi-stage builds (non-root user), Docker Compose for full local stack |
| **Testing** | Unit tests (`@MockitoExtension`), controller tests (`@WebMvcTest`), idempotency guards |
| **Code Quality** | Lombok, MapStruct, `@Builder`, interface+impl pattern, constants classes, `@Transactional` |

---

## πŸ“¦ Module Structure

```
order-management-microservices/
β”‚
β”œβ”€β”€ common-lib/ # Shared library (NOT a Spring Boot app)
β”‚ └── src/main/java/com/orderms/common/
β”‚ β”œβ”€β”€ dto/ApiResponse.java # Generic response envelope
β”‚ β”œβ”€β”€ event/BaseEvent.java # Kafka event base class
β”‚ β”œβ”€β”€ event/OrderPlacedEvent.java # order-service β†’ payment-service
β”‚ β”œβ”€β”€ event/PaymentProcessedEvent.java # payment-service β†’ order + notification
β”‚ β”œβ”€β”€ event/OrderStatusChangedEvent.java # order-service β†’ notification-service
β”‚ β”œβ”€β”€ exception/BaseException.java
β”‚ └── util/KafkaTopics.java # Topic + group ID constants
β”‚
β”œβ”€β”€ api-gateway/ :8080 # Spring Cloud Gateway – JWT validation at edge
β”œβ”€β”€ user-service/ :8081 # Auth, JWT, user CRUD, Redis blacklist
β”œβ”€β”€ order-service/ :8082 # Order lifecycle, Kafka producer + consumer
β”œβ”€β”€ payment-service/:8083 # Payment processing, Kafka consumer + producer
β”œβ”€β”€ notification-service/:8084 # Email dispatch, Kafka consumer
β”‚
β”œβ”€β”€ infra/
β”‚ β”œβ”€β”€ prometheus/prometheus.yml # Scrape config for all 5 services
β”‚ └── grafana/provisioning/ # Auto-provisioned Prometheus datasource
β”‚
β”œβ”€β”€ scripts/
β”‚ β”œβ”€β”€ init-databases.sql # Creates all 4 PostgreSQL databases
β”‚ └── start-dev.sh # One-command dev stack launcher
β”‚
β”œβ”€β”€ docker-compose.yml # Full stack: 5 services + 4 DBs + Kafka + Redis + monitoring
β”œβ”€β”€ Dockerfile # Multi-stage build template
β”œβ”€β”€ pom.xml # Maven multi-module parent POM
└── README.md
```

---

## ⚑ Kafka Event Flow

```
User places order
β”‚
β–Ό
order-service ──[order.placed]──────────────────▢ payment-service
β”‚
β”‚ Simulates payment (85% success)
β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ [payment.processed] β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ β”‚ β”‚
β–Ό β–Ό β–Ό
order-service order-service notification-service
(Updates status: [order.status.changed] (Sends payment
PAID or FAILED) β”‚ success/failure
β”‚ β”‚ email)
β”‚ β–Ό
β”‚ notification-service
└────────▢ (Sends order status
update email)
```

---

## πŸ” Security Architecture

### JWT Token Flow

```
1. POST /api/v1/auth/register OR POST /api/v1/auth/login
β”‚
└──▢ user-service validates credentials
β”‚
└──▢ Issues: access_token (15 min) + refresh_token (7 days)

2. Every protected request:
Client sends: Authorization: Bearer
β”‚
└──▢ API Gateway validates JWT at edge
β”‚
└──▢ Forwards X-User-Id + X-User-Role headers to downstream

3. POST /api/v1/auth/logout
β”‚
└──▢ JTI (JWT ID) stored in Redis with TTL = remaining token lifetime
└──▢ Subsequent requests with this token are rejected (blacklisted)

4. POST /api/v1/auth/refresh
β”‚
└──▢ Valid refresh token β†’ new access token (refresh token reused)
```

### RBAC

| Role | Permissions |
|---|---|
| `ROLE_USER` | Place orders, view own orders/payments, manage own profile |
| `ROLE_ADMIN` | All of the above + list all users, all orders, all payments |
| `ROLE_MANAGER` | Intermediate access (extensible) |

---

## πŸš€ Quick Start

### Prerequisites

| Tool | Minimum Version |
|---|---|
| Java | 21 |
| Maven | 3.9 |
| Docker + Docker Compose | 24 |

## πŸš€ One-command startup πŸš€- just run one command and all sevices will be up and running (can be verified on Docker Desktop)

```bash
git clone https://github.com/rahul-ghadge/order-management-microservices.git
cd order-management-microservices
chmod +x scripts/start-dev.sh
./scripts/start-dev.sh
```

### Manual startup

```bash
# 1. Build
mvn clean install -DskipTests

# 2. Start infrastructure
docker-compose up -d postgres-user postgres-order postgres-payment postgres-notification \
redis zookeeper kafka kafka-ui

# 3. Wait for infra, then start services
sleep 20
docker-compose up -d user-service order-service payment-service notification-service api-gateway

# 4. Start monitoring
docker-compose up -d prometheus grafana
```

---

## 🌐 Service URLs

| Service | URL | Description |
|---|---|---|
| API Gateway | http://localhost:8080 | Single entry point |
| User Service | http://localhost:8081/swagger-ui.html | Auth + user management |
| Order Service | http://localhost:8082/swagger-ui.html | Order lifecycle |
| Payment Service | http://localhost:8083/swagger-ui.html | Payment records |
| Notification Service | http://localhost:8084/swagger-ui.html | Notification logs |
| Kafka UI | http://localhost:8090 | Topic / message browser |
| Prometheus | http://localhost:9090 | Metrics scraping |
| Grafana | http://localhost:3000 | Dashboards (admin/admin) |

---

## πŸ“‹ API Reference

### Authentication

```bash
# Register
curl -X POST http://localhost:8080/api/v1/auth/register \
-H "Content-Type: application/json" \
-d '{
"username": "rahulghadage",
"email": "rahul@example.com",
"password": "stringP@ssw0rd",
"firstName": "Rahul",
"lastName": "ghadage"
}'

# Login
curl -X POST http://localhost:8080/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{ "usernameOrEmail": "john@example.com", "password": "Password1" }'

# Save the token
TOKEN=""

# Logout (blacklists token in Redis)
curl -X POST http://localhost:8080/api/v1/auth/logout \
-H "Authorization: Bearer $TOKEN"
```

### Place an Order

```bash
curl -X POST http://localhost:8080/api/v1/orders \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"userEmail": "rahul@example.com",
"shippingAddress": "123 Main Street, New York, NY 10001",
"currency": "USD",
"items": [
{ "productId": "PROD-001", "productName": "Laptop Pro", "quantity": 1, "unitPrice": 1299.99 },
{ "productId": "PROD-002", "productName": "USB-C Hub", "quantity": 2, "unitPrice": 49.99 }
]
}'
```

After placing the order, watch the Kafka event chain:
1. `order.placed` β†’ payment-service processes payment (85% success rate)
2. `payment.processed` β†’ order-service updates status; notification-service sends email
3. `order.status.changed` β†’ notification-service sends status email

```bash
# Check order status (cached in Redis)
curl http://localhost:8080/api/v1/orders/ \
-H "Authorization: Bearer $TOKEN"

# Check payment result
curl http://localhost:8080/api/v1/payments/order/ \
-H "Authorization: Bearer $TOKEN"

# Check notification logs
curl http://localhost:8080/api/v1/notifications/order/ \
-H "Authorization: Bearer $TOKEN"
```

### Cancel an Order (only PENDING or CONFIRMED)

```bash
curl -X PATCH http://localhost:8080/api/v1/orders//cancel \
-H "Authorization: Bearer $TOKEN"
```

---

## πŸ—ƒοΈ Database Schema

Each service owns its own PostgreSQL database (Database-per-Service pattern):

| Service | Database | Key Tables |
|---|---|---|
| user-service | `user_db` | `users` |
| order-service | `order_db` | `orders`, `order_items` |
| payment-service | `payment_db` | `payments` |
| notification-service | `notification_db` | `notification_logs` |

---

## πŸ“Š Observability

### Health Checks

```bash
curl http://localhost:8081/actuator/health
curl http://localhost:8082/actuator/health
curl http://localhost:8083/actuator/health
curl http://localhost:8084/actuator/health
```

### Prometheus Metrics

All services expose metrics at `/actuator/prometheus` β€” automatically scraped by Prometheus.

**Key metrics to monitor:**
- `http_server_requests_seconds` β€” request latency per endpoint
- `kafka_consumer_fetch_manager_records_consumed_total` β€” event throughput
- `jvm_memory_used_bytes` β€” heap usage per service
- `hikaricp_connections_active` β€” DB connection pool saturation
- `spring_cache_gets_total` β€” Redis cache hit/miss ratio

### Grafana

Navigate to http://localhost:3000, login with `admin/admin`.
The Prometheus datasource is auto-provisioned. Import dashboard ID **4701** (JVM Micrometer)
or **11378** (Spring Boot Statistics) from grafana.com/dashboards.

---

## πŸ§ͺ Running Tests

```bash
# All tests
mvn test

# Specific module
mvn test -pl user-service
mvn test -pl order-service
mvn test -pl payment-service
mvn test -pl notification-service

# Test coverage report
mvn test jacoco:report
```

### Test Inventory

| Module | Tests | Coverage |
|---|---|---|
| user-service | `UserServiceImplTest` (8 tests), `AuthControllerTest` (7 tests) | Auth, CRUD, validation |
| order-service | `OrderServiceImplTest` (5 tests), `OrderControllerTest` (7 tests) | Lifecycle, RBAC, cancel guards |
| payment-service | `PaymentEventProcessorTest` (4 tests) | Idempotency, success/failure, Kafka publish |
| notification-service | `NotificationEventConsumerTest` (5 tests) | Email dispatch, failure handling, NPE guards |

---

## βš™οΈ Configuration Reference

### Environment Variables

| Variable | Default | Description |
|---|---|---|
| `JWT_SECRET` | (long default) | HS256 signing secret – **change in production** |
| `DB_HOST` | `localhost` | PostgreSQL host |
| `DB_USERNAME` | `postgres` | PostgreSQL username |
| `DB_PASSWORD` | `postgres` | PostgreSQL password |
| `REDIS_HOST` | `localhost` | Redis host |
| `KAFKA_BOOTSTRAP_SERVERS` | `localhost:9092` | Kafka broker address |
| `NOTIFICATION_EMAIL_ENABLED` | `false` | Set `true` to send real emails |
| `MAIL_HOST` | `smtp.gmail.com` | SMTP server host |
| `MAIL_USERNAME` | β€” | SMTP username |
| `MAIL_PASSWORD` | β€” | SMTP password |

---

## πŸ›οΈ Architecture Decisions (ADR Summary)

| Decision | Choice | Rationale |
|---|---|---|
| Inter-service communication | Kafka (async) | Decouples services; payment/notification don't block order creation |
| Synchronous API | REST/JSON | Gateway routing + Swagger; simpler than gRPC for CRUD |
| Auth token storage | Stateless JWT + Redis blacklist | Horizontal scaling without shared session; instant logout |
| Database strategy | Database-per-service (separate PostgreSQL) | Independent schema evolution; blast radius containment |
| Caching | Redis | Shared infrastructure; supports rate limiting + token blacklist + entity cache |
| Idempotency | JTI-based blacklist + orderId guard in payment | Prevents double-processing on consumer retry |
| Secret management | Environment variables | 12-Factor App compliance; Kubernetes-compatible |

---

## πŸ“ License

Apache 2.0 β€” see [LICENSE](LICENSE).

## πŸ§ͺ Manuaal startup
image
image
image
image

---

## πŸš€ One-command startup
Run the script below (which is mentioned [here](#-one-command-startup---just-run-one-command-and-all-sevices-will-be-up-and-running-can-be-verified-on-docker-desktop)) from the command line

```bash
./scripts/start-dev.sh
```

Attached sample logs from local [here](https://github.com/rahul-ghadge/order-management-microservices/blob/main/order-management-microservices.log)

image

image