Skip to content

b3kt/aviation-api-wrapper

Repository files navigation

Aviation API Wrapper

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!

πŸ“‹ Overview

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.

Key Features

  • βœ… 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

πŸš€ Prerequisites

  • Java 21 or higher
  • Maven 3.9+ for build management
  • Internet connectivity for accessing aviationapi.com

πŸ“¦ Setup Instructions

1. Clone Repository

git clone <repository-url>
cd aviation-api-wrapper

2. Build Project

mvn clean install

The 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

3. Run Application

Option A: Using Maven

mvn spring-boot:run

Option B: Using Java JAR

java -jar target/aviation-api-0.0.1-SNAPSHOT.jar

Option C: Using Docker

# Build image
docker build -t aviation-api:latest .

# Run container
docker run -p 8080:8080 --name aviation-api aviation-api:latest

Option 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 down

Running services:

The application will start at http://localhost:8080


πŸ§ͺ Running Tests

Run All Tests

mvn test

Run Specific Test Class

mvn test -Dtest=AirportControllerIntegrationTest

Test Coverage

This project has 3 levels of testing:

  1. Unit Tests - GetAirportByIcaoCommandHandlerTest

    • Tests command handler in isolation
    • Mocks dependencies
  2. Integration Tests - AviationApiClientTest

    • Tests WebClient using MockWebServer
    • Verifies resilience patterns
  3. End-to-End Tests - AirportControllerIntegrationTest

    • Full Spring Boot context
    • Tests complete request flow
    • Validates HTTP responses

πŸ”Œ API Endpoints

Get Airport by ICAO Code

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/KJFK

Success 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 format
  • 404 Not Found - Airport not found
  • 429 Too Many Requests - Rate limit exceeded
  • 503 Service Unavailable - Circuit breaker open (upstream API down)

Health Check

curl http://localhost:8080/actuator/health

Metrics (Prometheus)

curl http://localhost:8080/actuator/metrics
curl http://localhost:8080/actuator/prometheus

API Documentation

Open browser to: http://localhost:8080/swagger-ui.html


πŸ—οΈ Architecture Decisions

Clean Architecture

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

Command-Executor Pattern

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 Choices

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

πŸ›‘οΈ Error Handling & Resilience

Resilience Patterns

The application implements multiple layers of resilience:

1. Circuit Breaker

Configuration:
- Sliding window: 10 calls
- Failure threshold: 50%
- Wait duration: 30 seconds
- Half-open calls: 3

Purpose: 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

2. Retry Logic

Configuration:
- Max attempts: 3
- Backoff: Exponential (500ms β†’ 1s β†’ 2s)
- Retry on: 500, 503, 504 errors
- Don't retry: 400, 404 errors

Purpose: Handles transient failures (network glitches, temporary unavailability)

3. Rate Limiter

Configuration:
- Limit: 100 requests per minute
- Timeout: 5 seconds to acquire permission

Purpose: Protects upstream API from overload, complies with rate limits

4. Timeout

Configuration:
- Request timeout: 3 seconds
- Overall timeout: 10 seconds

Purpose: Prevents indefinite waiting, frees up resources quickly

5. Caching

Configuration:
- Max size: 1000 entries
- TTL: 60 minutes
- Eviction: LRU (Least Recently Used)

Purpose: Reduces load on upstream API, improves response time

Error Response Format

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"
}

Failure Scenarios Handled

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

πŸ“Š Observability

Logging

  • 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

Metrics

Exposed via Prometheus format at /actuator/prometheus:

  • Request count & duration
  • Circuit breaker state
  • Cache hit/miss ratio
  • JVM metrics (memory, threads, GC)

Health Checks

GET /actuator/health

Returns:

  • Application status (UP/DOWN)
  • Disk space
  • Circuit breaker status

Distributed Tracing

  • W3C Trace Context propagation
  • Brave tracer implementation
  • Ready to export to Zipkin/Jaeger

πŸ”§ Configuration

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: 30s

To custom configuration, override via:

  • Environment variables
  • External application.yml
  • Command line arguments: --server.port=9090

πŸ€– AI-Generated Code Disclosure

Below are the parts assisted by AI tools and have been reviewed/validated:

Fully AI-Generated (with review):

  • Boilerplate configuration classes (WebClientConfiguration, CacheConfiguration)
  • OpenAPI configuration setup
  • Test scaffolding and mock data setup
  • Initial project structure with Maven dependencies

Human-Designed with AI Assistance:

  • Architecture decisions (Clean Architecture + Command Pattern)
  • Resilience patterns implementation
  • Business logic in command handlers
  • Error handling strategies
  • Domain model design

Fully Human-Written:

  • 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.


πŸ“ Project Structure

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

🎯 Assignment Requirements Coverage

βœ… Core 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

βœ… Scalability

  • Clean service layering (4 layers)
  • Stateless design
  • Ready for horizontal scaling
  • Efficient caching

βœ… Resilience

  • Retry logic with exponential backoff
  • Circuit breaker implementation
  • Fallback strategies
  • Timeout handling
  • Rate limiting

βœ… Extensibility

  • Not tightly coupled to provider
  • Port/Adapter pattern
  • Command pattern for new features

βœ… Observability

  • Structured logging
  • Error transparency
  • Metrics readiness (Prometheus)
  • Health checks

βœ… Deliverables

  • Executable Maven project
  • Complete README with instructions
  • Integration tests
  • Architecture documentation
  • Error handling notes
  • AI disclosure

πŸ§‘β€πŸ’» Development

Running in Development Mode

mvn spring-boot:run -Dspring-boot.run.profiles=dev

Enable Debug Logging

mvn spring-boot:run -Dlogging.level.com.github.b3kt.aviation=DEBUG

Running Tests with Coverage

mvn clean test jacoco:report
# Report: target/site/jacoco/index.html

πŸ“ž Support & Contact

For questions or issues:


πŸ“š References


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

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages