Spring Boot-based microservice to retrieve airport information using ICAO codes from AviationAPI.com.
π Quick Start: Want to start immediately? See QUICK_START.md for a 5-minute guide!
This project is a production-ready microservice implementation that provides a REST API to query airport information based on 4-character ICAO codes. It is built with a focus on scalability, resilience, and observability.
- β REST API endpoint for airport lookup by ICAO code
- β Integration with public aviation API (aviationapi.com)
- β Clean Architecture with 4 distinct layers
- β Command-Executor Pattern for extensibility
- β Comprehensive resilience patterns (Circuit Breaker, Retry, Rate Limiter, Timeout)
- β High-performance caching with Caffeine
- β Full observability (Logging, Metrics, Health Checks, Tracing)
- β Reactive non-blocking architecture with WebFlux
- β OpenAPI/Swagger documentation
- β Comprehensive test coverage
- Java 21 or higher
- Maven 3.9+ for build management
- Internet connectivity for accessing aviationapi.com
git clone <repository-url>
cd aviation-api-wrappermvn clean installThe build will:
- Compile all source code
- Run all unit & integration tests
- Package the application into an executable JAR
Expected output:
[INFO] BUILD SUCCESS
[INFO] Total time: XX.XXX s
Option A: Using Maven
mvn spring-boot:runOption B: Using Java JAR
java -jar target/aviation-api-0.0.1-SNAPSHOT.jarOption C: Using Docker
# Build image
docker build -t aviation-api:latest .
# Run container
docker run -p 8080:8080 --name aviation-api aviation-api:latestOption D: Using Docker Compose (with monitoring)
# Start all services (API + Prometheus + Grafana)
docker-compose up -d
# View logs
docker-compose logs -f aviation-api
# Stop all services
docker-compose downRunning services:
- Aviation API: http://localhost:8080
- Prometheus: http://localhost:9090
- Grafana: http://localhost:3000 (admin/admin)
The application will start at http://localhost:8080
mvn testmvn test -Dtest=AirportControllerIntegrationTestThis project has 3 levels of testing:
-
Unit Tests -
GetAirportByIcaoCommandHandlerTest- Tests command handler in isolation
- Mocks dependencies
-
Integration Tests -
AviationApiClientTest- Tests WebClient using MockWebServer
- Verifies resilience patterns
-
End-to-End Tests -
AirportControllerIntegrationTest- Full Spring Boot context
- Tests complete request flow
- Validates HTTP responses
GET /api/v1/airports/{icao}Path Parameters:
icao(required): 4-character ICAO code (e.g., KJFK, EGLL, YSSY)
Example Request:
curl http://localhost:8080/api/v1/airports/KJFKSuccess Response (200 OK):
{
"icaoCode": "KJFK",
"iataCode": "JFK",
"name": "John F Kennedy International Airport",
"city": "New York",
"country": "United States",
"coordinates": {
"latitude": 40.6398,
"longitude": -73.7789
},
"timezone": "America/New_York",
"elevationFeet": 13
}Error Responses:
400 Bad Request- Invalid ICAO code format404 Not Found- Airport not found429 Too Many Requests- Rate limit exceeded503 Service Unavailable- Circuit breaker open (upstream API down)
curl http://localhost:8080/actuator/healthcurl http://localhost:8080/actuator/metrics
curl http://localhost:8080/actuator/prometheusOpen browser to: http://localhost:8080/swagger-ui.html
This project implements Clean Architecture with 4 isolated layers:
βββββββββββββββββββββββββββββββββββββββββββββββ
β Presentation Layer β
β (Controllers, Exception Handlers, DTOs) β
ββββββββββββββββββ¬βββββββββββββββββββββββββββββ
β
ββββββββββββββββββΌβββββββββββββββββββββββββββββ
β Application Layer β
β (Commands, Handlers, Executor, Use Cases) β
ββββββββββββββββββ¬βββββββββββββββββββββββββββββ
β
ββββββββββββββββββΌβββββββββββββββββββββββββββββ
β Domain Layer β
β (Entities, Ports, Business Logic) β
βββββββββββββββββββββββββββββββββββββββββββββββ
β²
ββββββββββββββββββ΄βββββββββββββββββββββββββββββ
β Infrastructure Layer β
β (API Clients, Config, External Systems) β
βββββββββββββββββββββββββββββββββββββββββββββββ
Benefits:
- Testability: Business logic can be tested without external dependencies
- Maintainability: Changes in one layer do not affect others
- Provider Independence: Easy to swap aviation data providers
- Clear Boundaries: Each layer has a single responsibility
Implementation uses the Command-Executor Pattern for request handling:
- Command: Immutable data object representing an intent
- CommandHandler: Executes business logic for a specific command
- CommandExecutor: Router that dispatches commands to the appropriate handler
Benefits:
- Extensibility: Add new feature = create new command (Open/Closed Principle)
- Single Responsibility: Each handler focuses on one use case
- Auditability: Easy to add logging/metrics around command execution
- Testability: Commands and handlers can be tested independently
| Technology | Purpose | Rationale |
|---|---|---|
| Spring WebFlux | Reactive web framework | Non-blocking I/O for high throughput |
| Resilience4j | Resilience patterns | Modern library with Spring integration |
| Caffeine | Caching | High-performance in-memory cache |
| Micrometer | Metrics & Tracing | Industry standard observability |
| Springdoc OpenAPI | API Documentation | Auto-generate OpenAPI spec |
| Lombok | Boilerplate reduction | Clean, maintainable code |
The application implements multiple layers of resilience:
Configuration:
- Sliding window: 10 calls
- Failure threshold: 50%
- Wait duration: 30 seconds
- Half-open calls: 3Purpose: Prevents cascading failures when upstream API is down
- Open state: Immediately reject request without calling API
- Half-open state: Test if API has recovered
- Closed state: Normal operation
Configuration:
- Max attempts: 3
- Backoff: Exponential (500ms β 1s β 2s)
- Retry on: 500, 503, 504 errors
- Don't retry: 400, 404 errorsPurpose: Handles transient failures (network glitches, temporary unavailability)
Configuration:
- Limit: 100 requests per minute
- Timeout: 5 seconds to acquire permissionPurpose: Protects upstream API from overload, complies with rate limits
Configuration:
- Request timeout: 3 seconds
- Overall timeout: 10 secondsPurpose: Prevents indefinite waiting, frees up resources quickly
Configuration:
- Max size: 1000 entries
- TTL: 60 minutes
- Eviction: LRU (Least Recently Used)Purpose: Reduces load on upstream API, improves response time
All errors are returned in a consistent format:
{
"error": "Error Type",
"message": "Detailed error message",
"timestamp": "2025-11-30T10:30:00Z",
"path": "/api/v1/airports/INVALID"
}| Scenario | Handling Strategy |
|---|---|
| Upstream API down | Circuit breaker opens β 503 response |
| Transient network error | Retry with exponential backoff |
| Invalid ICAO code | Immediate 400 response (no retry) |
| Airport not found | 404 response (no retry) |
| Timeout | Cancel request after 3s β retry or fail |
| Rate limit hit | Queue request or 429 response |
- Structured logging with SLF4J
- Trace context included (traceId, spanId)
- Log levels: INFO (default), DEBUG (for troubleshooting)
Sample log:
2025-11-30 10:30:15.123 [http-nio-8080-exec-1] INFO [a1b2c3,d4e5f6] AirportController - Received request for airport with ICAO: KJFK
Exposed via Prometheus format at /actuator/prometheus:
- Request count & duration
- Circuit breaker state
- Cache hit/miss ratio
- JVM metrics (memory, threads, GC)
GET /actuator/healthReturns:
- Application status (UP/DOWN)
- Disk space
- Circuit breaker status
- W3C Trace Context propagation
- Brave tracer implementation
- Ready to export to Zipkin/Jaeger
Key configuration properties in application.yml:
# Server
server.port: 8080
# Aviation API
aviation.api.base-url: https://api.aviationapi.com
aviation.api.timeout-seconds: 3
aviation.api.max-retries: 3
# Cache
spring.cache.caffeine.spec: maximumSize=1000,expireAfterWrite=60m
# Resilience4j
resilience4j.circuitbreaker.instances.aviationApi:
failureRateThreshold: 50
waitDurationInOpenState: 30sTo custom configuration, override via:
- Environment variables
- External
application.yml - Command line arguments:
--server.port=9090
Below are the parts assisted by AI tools and have been reviewed/validated:
- Boilerplate configuration classes (
WebClientConfiguration,CacheConfiguration) - OpenAPI configuration setup
- Test scaffolding and mock data setup
- Initial project structure with Maven dependencies
- Architecture decisions (Clean Architecture + Command Pattern)
- Resilience patterns implementation
- Business logic in command handlers
- Error handling strategies
- Domain model design
- Core business logic
- Command validation logic
- Integration with aviation API
- Test scenarios and assertions
- Documentation and README
Note: All code has been understood, tested, and validated for production readiness.
aviation-api-wrapper/
βββ src/
β βββ main/
β β βββ java/com/github/b3kt/aviation/
β β β βββ domain/ # Core business logic
β β β β βββ model/ # Domain entities
β β β β βββ port/ # Port interfaces
β β β β βββ exception/ # Domain exceptions
β β β βββ application/ # Use cases
β β β β βββ command/ # Commands & handlers
β β β β βββ executor/ # Command executor
β β β β βββ dto/ # Application DTOs
β β β βββ infrastructure/ # External integrations
β β β β βββ client/ # API clients
β β β β βββ config/ # Spring configurations
β β β βββ presentation/ # API layer
β β β βββ controller/ # REST controllers
β β β βββ exception/ # Exception handlers
β β βββ resources/
β β βββ application.yml # Configuration
β βββ test/ # Test classes
βββ pom.xml # Maven dependencies
βββ README.md # This file
βββ assignment.md # Original requirements
- Accept HTTP requests to fetch airport by ICAO
- Query aviation API (https://aviationapi.com)
- Clean response format with key airport info
- Handle upstream failures gracefully
- Clean service layering (4 layers)
- Stateless design
- Ready for horizontal scaling
- Efficient caching
- Retry logic with exponential backoff
- Circuit breaker implementation
- Fallback strategies
- Timeout handling
- Rate limiting
- Not tightly coupled to provider
- Port/Adapter pattern
- Command pattern for new features
- Structured logging
- Error transparency
- Metrics readiness (Prometheus)
- Health checks
- Executable Maven project
- Complete README with instructions
- Integration tests
- Architecture documentation
- Error handling notes
- AI disclosure
mvn spring-boot:run -Dspring-boot.run.profiles=devmvn spring-boot:run -Dlogging.level.com.github.b3kt.aviation=DEBUGmvn clean test jacoco:report
# Report: target/site/jacoco/index.htmlFor questions or issues:
- Check assignment.md for requirements
- Review walkthrough.md for implementation details
- Check console logs for troubleshooting
Notes:
- assignment.md is a scope for ai assisted development
- walkthrough.md is an initial boilerplate implementation plan generated using Claude Sonnet 4.5
Built with β€οΈ using Clean Architecture principles