A production-grade microservice that aggregates user data from external APIs with enterprise patterns including circuit breakers, caching, comprehensive observability, and reactive support.
- Modern Stack: Java 21, Spring Boot 3.4, WebClient (reactive HTTP client)
- Resilience Patterns: Circuit breaker, retry, and timeout via Resilience4j
- Caching: In-memory caching with Caffeine for improved performance
- Observability: Micrometer metrics, Prometheus integration, structured logging with correlation IDs
- API Documentation: OpenAPI 3.0 with Swagger UI
- Containerization: Multi-stage Dockerfile, Docker Compose with optional monitoring stack
- Testing: Comprehensive unit tests, integration tests with WireMock, architecture tests with ArchUnit
- CI/CD: GitHub Actions pipeline with security scanning
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────────────┐
│ │ │ │ │ JSONPlaceholder API │
│ HTTP Client │────▶│ Controller │────▶│ (External Service) │
│ │ │ │ │ │
└─────────────────┘ └────────┬────────┘ └─────────────────────────┘
│ ▲
▼ │
┌─────────────────┐ │
│ │ │
│ Service │─────────────────┤
│ │ │
└────────┬────────┘ │
│ │
▼ │
┌─────────────────┐ │
│ API Client │─────────────────┘
│ (WebClient) │
│ │
│ ┌─────────────┐ │
│ │Circuit Brk. │ │
│ │Retry │ │
│ │Timeout │ │
│ └─────────────┘ │
└─────────────────┘
- Java 21 or later
- Maven 3.9+ (or use the included Maven wrapper)
- Docker (optional, for containerized deployment)
# Clone the repository
git clone https://github.com/welt/user-data-aggregator.git
cd user-data-aggregator
# Build the application
./mvnw clean package
# Run the application
./mvnw spring-boot:run
# Or run the JAR directly
java -jar target/user-data-aggregator-2.0.0.jarThe application will start at http://localhost:8080.
# Build and run with Docker Compose
docker-compose up --build
# With monitoring stack (Prometheus + Grafana)
docker-compose --profile monitoring up --build| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/users/{userId}/data |
Get aggregated user data with posts |
| GET | /api/v1/users/{userId}/data/reactive |
Reactive endpoint for user data |
| GET | /api/v1/users/{userId} |
Get user details only |
| GET | /api/v1/users/{userId}/posts |
Get user's posts only |
curl -X GET "http://localhost:8080/api/v1/users/1/data" \
-H "Accept: application/json" \
-H "X-Correlation-ID: my-request-123"{
"user": {
"id": 1,
"name": "Leanne Graham",
"username": "Bret",
"email": "Sincere@april.biz",
"address": {
"street": "Kulas Light",
"suite": "Apt. 556",
"city": "Gwenborough",
"zipcode": "92998-3874",
"geo": {
"latitude": "-37.3159",
"longitude": "81.1496"
}
},
"phone": "1-770-736-8031 x56442",
"website": "hildegard.org",
"company": {
"name": "Romaguera-Crona",
"catchPhrase": "Multi-layered client-server neural-net",
"bs": "harness real-time e-markets"
}
},
"posts": [
{
"id": 1,
"userId": 1,
"title": "sunt aut facere...",
"body": "quia et suscipit..."
}
],
"fetchedAt": "2024-01-15T10:30:00Z",
"postCount": 10
}- Swagger UI:
http://localhost:8080/swagger-ui.html - OpenAPI Spec:
http://localhost:8080/v3/api-docs
| Endpoint | Description |
|---|---|
/actuator/health |
Application health status |
/actuator/health/liveness |
Kubernetes liveness probe |
/actuator/health/readiness |
Kubernetes readiness probe |
/actuator/info |
Application info (Git, build) |
/actuator/metrics |
Application metrics |
/actuator/prometheus |
Prometheus metrics endpoint |
/actuator/caches |
Cache statistics |
| Variable | Description | Default |
|---|---|---|
SPRING_PROFILES_ACTIVE |
Active profile (dev, prod) | - |
APP_API_JSONPLACEHOLDER_BASE_URL |
External API base URL | https://jsonplaceholder.typicode.com |
APP_API_JSONPLACEHOLDER_CONNECTION_TIMEOUT |
Connection timeout | 5s |
APP_API_JSONPLACEHOLDER_READ_TIMEOUT |
Read timeout | 10s |
- default: Standard configuration
- dev: Development with debug logging
- prod: Production with optimized settings
- test: Test configuration with WireMock
# Run all tests
./mvnw clean verify
# Run unit tests only
./mvnw test
# Run integration tests only
./mvnw verify -DskipUnitTests
# Generate coverage report
./mvnw test jacoco:report
# Report available at: target/site/jacoco/index.htmlresilience4j:
circuitbreaker:
instances:
jsonPlaceholder:
sliding-window-size: 10
failure-rate-threshold: 50
wait-duration-in-open-state: 30sresilience4j:
retry:
instances:
jsonPlaceholder:
max-attempts: 3
wait-duration: 500ms
enable-exponential-backoff: true# Start with monitoring stack
docker-compose --profile monitoring up -d
# Access services
# - Application: http://localhost:8080
# - Prometheus: http://localhost:9090
# - Grafana: http://localhost:3000 (admin/admin)http_server_requests- HTTP request metricsapi_client_get_user- External API call timing for usersapi_client_get_posts- External API call timing for postsservice_user_data_get- Service layer aggregation timingresilience4j_circuitbreaker_*- Circuit breaker metricscache_*- Cache hit/miss statistics
src/
├── main/
│ ├── java/com/welt/data/
│ │ ├── Application.java # Main application entry
│ │ ├── client/ # External API clients
│ │ ├── config/ # Configuration classes
│ │ ├── controller/ # REST controllers
│ │ ├── dto/ # Data transfer objects (records)
│ │ ├── exception/ # Custom exceptions & handlers
│ │ └── service/ # Business logic
│ └── resources/
│ ├── application.yml # Main configuration
│ ├── application-dev.yml # Development profile
│ ├── application-prod.yml # Production profile
│ └── application-test.yml # Test profile
├── test/
│ └── java/com/welt/data/
│ ├── architecture/ # ArchUnit tests
│ ├── client/ # Client tests
│ ├── controller/ # Controller tests
│ └── service/ # Service tests
├── .github/workflows/ # CI/CD pipelines
├── docker/ # Docker configuration
├── Dockerfile # Multi-stage build
└── docker-compose.yml # Container orchestration
| Component | Technology |
|---|---|
| Language | Java 21 |
| Framework | Spring Boot 3.4.1 |
| HTTP Client | WebClient (Spring WebFlux) |
| Resilience | Resilience4j |
| Caching | Caffeine |
| API Docs | SpringDoc OpenAPI 3 |
| Metrics | Micrometer + Prometheus |
| Testing | JUnit 5, MockMvc, WireMock, ArchUnit |
| Build | Maven |
| Container | Docker |
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
- JSONPlaceholder - Free fake API for testing
- Spring Boot - Application framework
- Resilience4j - Fault tolerance library