Production-ready weather aggregation service demonstrating Hexagonal Architecture (Ports & Adapters), Clean Architecture principles, and modern Java 17+ features.
Enterprise-grade weather API service that aggregates data from multiple weather providers through a clean, unified interface. Built to demonstrate architectural patterns and best practices in modern Java development.
- β Hexagonal Architecture - Complete separation of business logic from technical concerns
- β Provider Abstraction - Easily add new weather data sources
- β Normalized API - Consistent response format regardless of provider
- β Modern Java 17+ - Records, Pattern Matching, Text Blocks
- β Spring Boot 3.x - Jakarta EE, native compilation ready
- β Docker Support - Multi-stage optimized containers
- β API Documentation - Swagger/OpenAPI integration
- β Request Logging - Complete audit trail of API calls
weather-api/
βββ domain/ # Core business logic (zero external dependencies)
β βββ model/ # Entities & Value Objects
β βββ ports/ # Interface contracts
β β βββ in/ # Primary ports (use cases)
β β βββ out/ # Secondary ports (persistence, external APIs)
β βββ services/ # Business logic implementation
β
βββ shared/ # Cross-cutting concerns
β βββ dto/ # Data Transfer Objects
β βββ exception/ # Domain exceptions
β
βββ application/ # Application orchestration
β βββ service/ # Application services
β βββ config/ # Application configuration
β
βββ adapters/ # Technical implementations
β βββ in/rest/ # REST controllers
β βββ out/ # External integrations
β βββ persistence/ # Database implementations
β βββ api/ # External API integrations
β
βββ bootstrap/ # Application initialization
βββ config/ # Global configuration
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β REST API Layer β
β (Adapters - In) β
βββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββΌββββββββββββββββββββββββββββββββββ
β Application Services β
β (Orchestration Layer) β
βββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββΌββββββββββββββββββββββββββββββββββ
β Domain Layer (Business Logic) β
β - Weather Entity - Ports (Interfaces) β
β - Temperature VO - Use Cases β
β - Wind Speed VO - Domain Services β
βββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββΌββββββββββββββββββββββββββββββββββ
β Adapters - Out β
β ββββββββββββββββ ββββββββββββββββ β
β β OpenWeather β β H2 Database β β
β β Adapter β β Adapter β β
β ββββββββββββββββ ββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- Java 17 - Modern Java features (Records, Pattern Matching, Text Blocks)
- Spring Boot 3.x - Jakarta EE framework
- Spring Data JPA - Data persistence
- H2 Database - Embedded database
- Maven - Build tool
- Spring Web - REST API
- Swagger/OpenAPI - API documentation
- Jakarta Validation - Input validation
- Docker - Containerization
- Docker Compose - Multi-container orchestration
- Makefile - Build automation
// Records for immutable DTOs
public record WeatherResponse(
String city,
Temperature temperature,
String condition,
Wind wind
) {}
// Pattern Matching
if (provider instanceof OpenWeatherAdapter adapter) {
return adapter.fetchWeather(city);
}
// Text Blocks
String query = """
SELECT * FROM weather_log
WHERE city = ?
AND timestamp > ?
""";- Java 17 or higher
- Maven 3.8+
- Docker & Docker Compose (optional)
# Clone repository
git clone https://github.com/javiernuma/weater-proxy.git
cd weater-proxy
# Build and run with Docker
docker-compose up --build
# Or use Makefile
make docker-build
make docker-run# Build
mvn clean package
# Run
mvn -pl bootstrap spring-boot:run- API Base: http://localhost:8080
- Swagger UI: http://localhost:8080/swagger-ui.html
- H2 Console: http://localhost:8080/h2-console
- Health Check: http://localhost:8080/actuator/health
GET /api/weather/{city}?source={provider}&config={json}| Parameter | Type | Required | Description |
|---|---|---|---|
| city | path | Yes | City name |
| source | query | No | Weather provider (default: mock) |
| config | query | No | Provider-specific configuration (JSON) |
Basic Request (Mock Provider):
curl http://localhost:8080/api/weather/Madrid?source=mockOpenWeather Provider:
curl "http://localhost:8080/api/weather/Madrid?source=openweather&config={\"apiKey\":\"YOUR_API_KEY\"}"Using Makefile:
make api-test{
"city": "Madrid",
"temperature": {
"value": 25.5,
"unit": "Β°C"
},
"condition": "Sunny",
"wind": {
"speed": 12.3,
"unit": "km/h"
}
}| Provider | Status | Description |
|---|---|---|
| Mock | β Active | Simulated data for testing |
| OpenWeather | β Active | OpenWeatherMap API integration |
| WeatherStack | π Planned | WeatherStack API |
| AccuWeather | π Planned | AccuWeather API |
Implement the WeatherProvider port:
public interface WeatherProvider {
Weather fetchWeather(String city, ProviderConfig config);
}Example implementation:
@Component("customProvider")
public class CustomWeatherAdapter implements WeatherProvider {
@Override
public Weather fetchWeather(String city, ProviderConfig config) {
// Your implementation
}
}make docker-build # Build Docker image
make docker-run # Start containers
make docker-logs # View logs
make docker-stop # Stop containers
make docker-clean # Remove everything# Build and start
docker-compose up --build
# Start in background
docker-compose up -d
# View logs
docker-compose logs -f
# Stop
docker-compose downCreate .env file:
SPRING_PROFILES_ACTIVE=docker
OPENWEATHER_API_KEY=your_api_key_here
OPENWEATHER_ENABLED=true
LOGGING_LEVEL_ROOT=INFO- Hexagonal Architecture - Ports & Adapters separation
- Dependency Inversion - Core depends on abstractions
- Strategy Pattern - Interchangeable weather providers
- Factory Pattern - Provider instantiation
- Repository Pattern - Data access abstraction
- DTO Pattern - API boundary objects
β
Single Responsibility - Each class has one job
β
Open/Closed - Open for extension (new providers), closed for modification
β
Liskov Substitution - Providers are interchangeable
β
Interface Segregation - Focused port interfaces
β
Dependency Inversion - High-level modules independent of low-level details
make help # Show all commands
make build # Build project
make test # Run tests
make coverage # Generate coverage report
make run # Run locally
make verify # Full verification
make swagger # Open Swagger UI
make h2-console # Open H2 Consolemvn clean package # Build
mvn test # Run tests
mvn verify # Integration tests
mvn jacoco:report # Coverage report- β Input validation with Jakarta Validation
- β SQL injection prevention (JPA)
- β API key management (externalized config)
- β Docker non-root user
- β Error handling without data leakage
- Comprehensive Testing - Unit, integration, and contract tests
- Caching Layer - Redis integration for performance
- Rate Limiting - API request throttling
- Authentication - JWT-based security
- Circuit Breaker - Resilience4j integration
- Monitoring - Prometheus metrics
- More Providers - WeatherStack, AccuWeather
Javier Vidal Numa Mendoza
Software Architect specializing in:
- Clean Architecture & Hexagonal Architecture
- Domain-Driven Design
- Event-Driven Systems
- Modern Java Development
- Cloud-Native Applications
This project is licensed under the MIT License - see the LICENSE file for details.
- β‘ Hexagonal Architecture - Ports & Adapters pattern
- π― Clean Code - SOLID principles
- π Modern Java - Java 17+ features
- π¦ Provider Abstraction - Extensible design
- π³ Docker Ready - Production deployment
- π Well-Documented - Clear structure & examples
Built with β€οΈ demonstrating architectural excellence and modern Java practices