Skip to content

javiernuma/weather-api-hexagonal

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

14 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

☁️ Weather API - Hexagonal Architecture

Production-ready weather aggregation service demonstrating Hexagonal Architecture (Ports & Adapters), Clean Architecture principles, and modern Java 17+ features.

Java Spring Boot Hexagonal Docker

🎯 Overview

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.

Key Features

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

πŸ—οΈ Architecture

Hexagonal Architecture Layers

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

Architecture Diagram

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚               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    β”‚                 β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ› οΈ Tech Stack

Core Technologies

  • 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

API & Documentation

  • Spring Web - REST API
  • Swagger/OpenAPI - API documentation
  • Jakarta Validation - Input validation

DevOps

  • Docker - Containerization
  • Docker Compose - Multi-container orchestration
  • Makefile - Build automation

Modern Java 17 Features Used

// 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 > ?
    """;

πŸš€ Quick Start

Prerequisites

  • Java 17 or higher
  • Maven 3.8+
  • Docker & Docker Compose (optional)

Installation & Run

Option 1: Using Docker (Recommended)

# 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

Option 2: Using Maven

# Build
mvn clean package

# Run
mvn -pl bootstrap spring-boot:run

Access Points


πŸ“‘ API Usage

Get Weather Data

GET /api/weather/{city}?source={provider}&config={json}

Parameters

Parameter Type Required Description
city path Yes City name
source query No Weather provider (default: mock)
config query No Provider-specific configuration (JSON)

Examples

Basic Request (Mock Provider):

curl http://localhost:8080/api/weather/Madrid?source=mock

OpenWeather Provider:

curl "http://localhost:8080/api/weather/Madrid?source=openweather&config={\"apiKey\":\"YOUR_API_KEY\"}"

Using Makefile:

make api-test

Normalized Response

{
  "city": "Madrid",
  "temperature": {
    "value": 25.5,
    "unit": "Β°C"
  },
  "condition": "Sunny",
  "wind": {
    "speed": 12.3,
    "unit": "km/h"
  }
}

πŸ”Œ Weather Providers

Implemented Providers

Provider Status Description
Mock βœ… Active Simulated data for testing
OpenWeather βœ… Active OpenWeatherMap API integration
WeatherStack πŸ”„ Planned WeatherStack API
AccuWeather πŸ”„ Planned AccuWeather API

Adding New Providers

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

🐳 Docker Usage

Using Makefile

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

Using Docker Compose

# Build and start
docker-compose up --build

# Start in background
docker-compose up -d

# View logs
docker-compose logs -f

# Stop
docker-compose down

Environment Variables

Create .env file:

SPRING_PROFILES_ACTIVE=docker
OPENWEATHER_API_KEY=your_api_key_here
OPENWEATHER_ENABLED=true
LOGGING_LEVEL_ROOT=INFO

πŸ›οΈ Architecture Patterns

Design Patterns Used

  • 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

SOLID Principles

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


πŸ“¦ Build Commands

Using Makefile

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 Console

Using Maven

mvn clean package   # Build
mvn test           # Run tests
mvn verify         # Integration tests
mvn jacoco:report  # Coverage report

πŸ”’ Security Features

  • βœ… Input validation with Jakarta Validation
  • βœ… SQL injection prevention (JPA)
  • βœ… API key management (externalized config)
  • βœ… Docker non-root user
  • βœ… Error handling without data leakage

πŸ“ˆ Roadmap

Planned Features

  • 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

πŸ“š Additional Resources


πŸ‘¨β€πŸ’» Author

Javier Vidal Numa Mendoza

Software Architect specializing in:

  • Clean Architecture & Hexagonal Architecture
  • Domain-Driven Design
  • Event-Driven Systems
  • Modern Java Development
  • Cloud-Native Applications

LinkedIn GitHub Email


πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.


🌟 Highlights

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

About

weather-proxy

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published