A Spring Boot multi-module microservices project demonstrating :
- Domain + persistence layering
- Transactional outbox pattern
- RabbitMQ async messaging
- Idempotent consumer processing in wallet service
- API Gateway with Circuit Breaker and Retry/Backoff
- Gateway hardening (secure headers, request size, timeouts)
- IAM/IdP with Keycloak and JWT validation at API Gateway
- OpenAPI/Swagger for gateway and services
- Flyway migration-based schema management (booking/wallet)
- Distributed tracing with Zipkin
- Local (H2) and Dev/Prod (PostgreSQL) profile strategy
common: shared domain/events/outbox componentsservices:booking-service: booking API + outbox publisherservices:wallet-service: wallet API + RabbitMQ consumerservices:api-gateway: edge routing + resilience policiesservices:event-service: event catalog APIservices/ui-app: Angular + TypeScript frontend
- Client calls Booking API (
POST /bookings) - Booking is stored in DB
- BookingCreated event is stored in outbox table in same transaction
- Scheduler publishes outbox events to RabbitMQ
- Wallet service consumes booking events
- Wallet service enforces idempotency using
processed_events
- Java 21
- Spring Boot 3.2.x
- Spring Data JPA
- RabbitMQ
- PostgreSQL / H2
- Spring Cloud Gateway + Resilience4j
- Micrometer Tracing + Zipkin
- JUnit 5 + Mockito + Testcontainers
- Docker + Docker Compose
- JDK 21 (
java -version) - Docker Desktop (required for compose and Testcontainers integration tests)
- Optional: Postman/Newman, Robot Framework
- GitHub Actions are pinned to full commit SHAs for security and reproducibility.
- Update pinned SHAs periodically (e.g., monthly) or when you need a new action release.
./gradlew clean buildBuild only one module:
./gradlew :services:booking-service:build
./gradlew :services:wallet-service:build
./gradlew :services:api-gateway:build
./gradlew :services:event-service:buildBuild UI app:
cd services/ui-app
npm install
npm run build:prodCreate local env file first:
cp .env.example .envUpdate .env with strong local values, then run:
./gradlew clean build
docker compose up --buildServices:
- API Gateway:
http://localhost:8081 - UI App:
http://localhost:6767 - Keycloak (IdP):
http://localhost:9090 - RabbitMQ UI:
http://localhost:15672(guest/guest) - Zipkin UI:
http://localhost:9411 - Prometheus:
http://localhost:9092 - Grafana:
http://localhost:3000(admin/admin)
Note: booking, wallet, and event services are internal-only in Docker Compose and intentionally not exposed to host ports.
Stop stack:
docker compose down -vTerminal 1:
./gradlew :services:booking-service:bootRunTerminal 2:
./gradlew :services:wallet-service:bootRunTerminal 3:
./gradlew :services:api-gateway:bootRunTerminal 4:
cd services/ui-app
npm install
npm startNote: RabbitMQ still needs to be running for messaging flows.
local(default): H2 in-memory DBdev: PostgreSQLprod: PostgreSQL + stricter JPA validation
Run with a specific profile:
SPRING_PROFILES_ACTIVE=dev ./gradlew :services:booking-service:bootRun- Realm:
eventflowx - Client:
eventflowx-ui(public client) - IAM role model:
- Base roles:
user,admin - Fine-grained roles:
event.read,booking.write,wallet.read,wallet.credit
- Base roles:
- IAM groups:
customers: mapped to user + functional rolesops-admins: mapped to admin + functional roles
- Token/session policy:
- Access token lifespan: 15 minutes
- SSO idle timeout: 30 minutes
- SSO max lifespan: 8 hours
- Refresh token rotation enabled (
revokeRefreshToken=true)
- Demo users:
eventflowx-user/eventflowx-passeventflowx-admin/eventflowx-admin-pass
Get access token:
TOKEN=$(curl -s -X POST "http://localhost:9090/realms/eventflowx/protocol/openid-connect/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=password" \
-d "client_id=eventflowx-ui" \
-d "username=eventflowx-user" \
-d "password=eventflowx-pass" | sed -n 's/.*\"access_token\":\"\\([^\"]*\\)\".*/\\1/p')Gateway authorization mapping:
GET /events/**->event.readoradminPOST /bookings/**->booking.writeoradminPOST /payments/**->wallet.creditoradminGET /wallets/**->adminPOST /wallets/*/credit->adminPOST /admin/events/**andGET /admin/events/**->admin
- API Gateway docs:
http://localhost:8081/swagger-ui.html - Booking service docs:
http://localhost:8080/swagger-ui.html(local run) - Wallet service docs:
http://localhost:8084/swagger-ui.html(local run) - Event service docs:
http://localhost:8082/swagger-ui.html(local run)
- All external gateway routes are versioned under
/api/v1. - Unversioned routes remain temporarily for backward compatibility and will be removed after a deprecation window.
- Breaking changes require a new major version path (
/api/v2). - Non-breaking additions can ship within the same version.
See docs/14-api-versioning.md for the full contract policy.
Create a booking through gateway:
curl -X POST http://localhost:8081/api/v1/bookings \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"userId":"eventflowx-user","eventId":"event-001","eventName":"concert-night"}'Charge payment (post-booking):
curl -X POST http://localhost:8081/api/v1/payments/charge \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"bookingId":"<booking-id>","userId":"eventflowx-user","paymentGateway":"RAZORPAY","paymentMethodType":"UPI","amount":99}'List events:
curl -H "Authorization: Bearer $TOKEN" http://localhost:8081/api/v1/eventsRun all unit tests:
./gradlew testRun module unit tests:
./gradlew :services:booking-service:test
./gradlew :services:wallet-service:test
./gradlew :services:api-gateway:test
./gradlew :services:event-service:testWorkflow: .github/workflows/build.yml
- Build job runs on push and PR.
- Sonar job runs on PR when these repository secrets are present:
SONAR_TOKENSONAR_HOST_URLSONAR_PROJECT_KEY
- Sonar quality gate is executed as part of the PR workflow.
Recommended: mark this workflow as a required status check in branch protection once secrets are configured.
Run UI unit tests:
cd services/ui-app
npm testIntegration tests use Spring Boot + Testcontainers and require Docker.
Run integration-heavy modules:
./gradlew :services:booking-service:test :services:wallet-service:testIf Docker is not available, Testcontainers tests are auto-skipped.
- Booking integration test uses PostgreSQL + RabbitMQ containers.
- Wallet integration test validates idempotent event consumption behavior.
If you maintain Postman tests, keep files in:
tests/newman/EventFlowX.postman_collection.jsontests/newman/local.postman_environment.json
Run with Newman:
newman run tests/newman/EventFlowX.postman_collection.json \
-e tests/newman/local.postman_environment.jsonOptional HTML report:
newman run tests/newman/EventFlowX.postman_collection.json \
-e tests/newman/local.postman_environment.json \
-r cli,htmlextraIf you maintain Robot tests, keep files in:
tests/robot/
Run:
robot -d reports tests/robotRun a specific suite:
robot -d reports tests/robot/booking_flow.robot- Trace/span IDs are included in service log patterns.
- Zipkin endpoint is configurable via
ZIPKIN_ENDPOINT. - Actuator endpoints exposed:
health,info,metrics,prometheus.
Gateway provides:
- Circuit breaker for booking, wallet, and event routes
- Retry with exponential backoff
- Fallback endpoints:
/fallback/bookings/fallback/wallets/fallback/events
.
├── common
├── services
│ ├── api-gateway
│ ├── booking-service
│ ├── wallet-service
│ ├── event-service
│ └── ui-app
├── docker
│ └── postgres/init.sql
├── docker-compose.yml
└── docs
A practical pipeline order:
./gradlew clean test./gradlew build- Build/push Docker images
- Run compose smoke test
- Publish test + coverage reports
Good additions for a production-ready README and repo:
- API contract section with request/response examples per endpoint
- Sequence diagram for booking -> outbox -> RabbitMQ -> wallet flow
- Failure-mode matrix (duplicate event, broker down, DB down, partial failure)
- Migration strategy (
FlywayorLiquibase) and rollback notes - Security model (authn/authz, secrets strategy, TLS, mTLS)
- Performance baseline and load-test instructions (k6/JMeter/Gatling)
- SLO/SLI definitions and alerting strategy
- Contribution guidelines + coding standards + commit conventions
- Release/versioning policy and changelog workflow
- Troubleshooting playbook (common errors and fixes)
See:
docs/01-architecture.MDdocs/02-distributed-patterns.mddocs/06-observability.mddocs/08-testing-strategy.mddocs/13-local-setup.md