Skip to content

CauaSND/WeatherAPI

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

31 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Weather API - REST Backend Service

A high-performance REST API built with Java and Spring Boot for retrieving real-time weather data. This project integrates with the OpenWeatherMap API, implementing a resilient architecture optimized with Redis distributed caching and comprehensive unit test coverage.

Developed by: CauΓ£ Silva
Email: caua.sndias@gmail.com
GitHub: https://github.com/CauaSND/WeatherAPI


πŸ“‹ Project Objective

The Weather API provides a robust backend service for querying current weather information by city and state. The system implements clean architecture patterns with strategy-based dependency injection, enabling flexible infrastructure swapping without affecting business logic. This project demonstrates production-grade Java development practices including efficient caching, proper exception handling, and comprehensive API security.


🎯 Core Features

  • Real-time Weather Data: Retrieve current temperature, humidity, pressure, and "feels like" metrics via OpenWeatherMap integration
  • Efficient Caching: Distributed Redis cache with intelligent TTL strategies (15 minutes for weather, 30 days for geolocation)
  • State-aware City Matching: Automatic Unicode normalization to disambiguate cities with identical names across different Brazilian states
  • Clean Architecture: Strict separation of concerns with interface-based adapters for seamless infrastructure replacement
  • Comprehensive Error Handling: Custom exception hierarchy with global error handler providing structured error responses
  • Automated Testing: JUnit 5 + Mockito test suite covering adapter layer and critical business logic

πŸ› οΈ Technology Stack

Component Technology
Language Java 21
Framework Spring Boot 3.x (Spring Web)
Cache Redis 7+ with Jedis Client
Testing JUnit 5, Mockito
Serialization Gson
Build Tool Maven 3.x
Code Utilities Project Lombok
Thymeleaf (RenderizaΓ§Γ£o do Front-end)
Docker (ContainerizaΓ§Γ£o)

πŸ“ System Architecture (Ports & Adapters / Hexagonal)

The codebase follows hexagonal architecture principles to ensure infrastructure agnosticism:

com.api.WeatherAPI/
β”œβ”€β”€ config/              # Bean configuration & infrastructure setup
β”œβ”€β”€ controllers/         # HTTP endpoints (routing only)
β”œβ”€β”€ services/            # Business logic with cache-first pattern
β”œβ”€β”€ adapters/            # Port implementations
β”‚   β”œβ”€β”€ WeatherGateway   # Interface for external API calls
β”‚   β”œβ”€β”€ OpenWeatherAdapter   # OpenWeatherMap API integration
β”‚   β”œβ”€β”€ WeatherCache     # Interface for caching abstraction
β”‚   └── RedisCache       # Redis persistence implementation
β”œβ”€β”€ dtos/                # Data transfer objects (Lombok @Builder)
└── expection/           # Custom exception hierarchy

Design Principle: Services depend only on interfaces (WeatherGateway, WeatherCache), never on concrete implementations. This allows swapping Redis for in-memory cache without modifying business logic.


πŸ”Œ API Endpoints

Get Current Weather

GET /current/{state}/{city}

Path Parameters:

  • state (string, required): Brazilian state name (normalized format, e.g., sao-paulo, rio-de-janeiro)
  • city (string, required): City name

Response:

{
  "temp": 28.5,
  "feels_like": 30.2,
  "humidity": 65,
  "pressure": 1013
}

Status Codes:

  • 200 OK: Weather data retrieved successfully
  • 404 Not Found: State/city combination not found
  • 500 Internal Server Error: OpenWeatherMap API failure or Redis connection issue

Get Available Cities

GET /location/cities/{city}

Path Parameters:

  • city (string, required): City name to search

Response:

[
  {
    "name": "SΓ£o Paulo",
    "state": "SΓ£o Paulo",
    "lat": -23.5505,
    "lon": -46.6333
  }
]

Status Codes:

  • 200 OK: City list retrieved successfully
  • 500 Internal Server Error: OpenWeatherMap API unavailable

πŸ”§ Environment Variables

Configure the following environment variables before running:

weatherkey     # OpenWeatherMap API key (required)
redisURL       # Redis host (default: localhost)
redisPORT      # Redis port (default: 6379)
redisPassword  # Redis authentication password

🐳 running with Docker

This is a Multi-stage Build in Docker, The entire instructure (API Spring Boot + Cache Redis) runs isolated within the same Docker network , make a safe comunication, fast and in a simulation enviroment

You do not need to have Java, Maven or Redis in your machine, only Dcker can compile and execute the whole application

⚠️ IMPORTANT (API Key): This project consumes real-time data from OpenWeather. To get real weather data, you need a valid API key. Otherwise, mock (false) data will be processed and returned.

πŸš€ Step by Step

(If you prefer to use mock(false) data, you can skip steps 1 and 3).

1. Get a key (If you want real data)

  1. open OpenWeather log-in with a free acount.
  2. Go to API key section and get your API key

2. Clone this repo

git clone [https://github.com/CauaSND/WeatherAPI.git](https://github.com/CauaSND/WeatherAPI.git)
cd WeatherAPI

3. Configure your credentials (.env)

The project has a file called .env.example. Do a copy of it and renome to .env and change only the weatherkey:

cp .env.example .env
weatherkey=your-key

Security note: Put '.env' in '.gitignore' before committing. The final '.env' file you generate is ignored by Git to ensure your private keys are never pushed to the public repository.

4. Run containers

With the .env file filled in the root, run the command below in the terminal to build the images and start all services on the same network:

docker compose up --build

5. Open your browser

Once Spring Boot has successfully booted in the terminal, open your browser and access the front-end screen in Thymeleaf: πŸ‘‰ http://localhost:8080

πŸ“Š Testing Strategy

  • Framework: JUnit 5 with MockitoExtension
  • Pattern: Given-When-Then structure with @BeforeEach fixture setup
  • Coverage: Focus on adapter layer and state-matching logic
  • Mocking: RestTemplate stubs for OpenWeatherMap API responses

Example test:

@ExtendWith (MockitoExtension.class)
class OpenWeatherAdapterTest {
    @Mock
    RestTemplate restTemplate;

    @InjectMocks
    OpenWeatherAdapter adapter;

    @Test
    void shouldMatchCityByNormalizedState () {
        // Given: Multiple results for city "Osasco"
        // When: Filter by state "sao-paulo"
        // Then: Return coordinates for SΓ£o Paulo entry
    }
}

πŸ” Caching Strategy

Resource TTL Key Format
Weather Data 15 minutes {cityName}
City Geolocation 30 days {cityName}Cities

The cache-first pattern ensures minimal external API calls and optimal response times:

REQUEST
  β†’ Cache HIT: Return cached data
  β†’ Cache MISS: Query OpenWeatherMap β†’ Cache result β†’ Return

🌍 State Normalization Logic

The system disambiguates cities with identical names across Brazilian states using Unicode-aware normalization:

// Input: state = "SΓ£o Paulo"
// Process:
//   1. Decompose accents (NFD): "Sa˜o Paulo"
//   2. Remove combining marks: "Sao Paulo"
//   3. Convert to lowercase: "sao paulo"
//   4. Replace spaces with hyphens: "sao-paulo"
// Output: "sao-paulo"

Example: City "Osasco" exists in both SΓ£o Paulo and ParanΓ‘ states. The API returns results for both; state parameter selects the correct one.


🚨 Exception Handling

Custom exceptions with HTTP status mapping:

  • LocationNotFoundException β†’ HTTP 404

    • Thrown when state/city combination not found
  • WeatherApiException β†’ HTTP 500

    • Thrown when OpenWeatherMap API fails or returns null

All exceptions are caught by @RestControllerAdvice global handler for consistent error responses.


πŸ“ Project Structure

  • src/main/java/com/api/WeatherAPI/ β€” Source code

    • controllers/ β€” REST endpoint handlers
    • services/ β€” Business logic layer
    • adapters/ β€” External integration ports
    • config/ β€” Spring beans and infrastructure configuration
    • dtos/ β€” Data transfer objects
    • expection/ β€” Custom exception classes
  • src/test/java/ β€” Unit tests


🀝 Contributing

For feature requests or bug reports, please open an issue on the GitHub repository.


πŸ“„ License

This project is provided as-is for educational and development purposes.


Last Updated: June 2026
Java Version: 21
Spring Boot Version: 3.x

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors