Skip to content

Latest commit

 

History

History
169 lines (127 loc) · 7.57 KB

File metadata and controls

169 lines (127 loc) · 7.57 KB

📁 Project Structure Overview – GeoLocateAPI

This document provides a clear overview of the folder and file responsibilities within the GeoLocateAPI project.
The architecture follows Clean Architecture + Hexagonal Architecture, ensuring each layer has a single, well‑defined purpose.


1. domain/ — Core Business Logic

Pure Java classes containing the domain models.
No Spring, no annotations, no external dependencies.

Files:

  • model/GeoLocationData.java
    Domain model representing geolocation information (lat/lon, country, region, city, timezone, ISP).
    Independent from provider DTOs or frameworks.

2. application/ — Use Cases, Ports & Cross-cutting Concerns

Orchestrates logic and defines the boundary between the domain and the outside world.

Files & folders:

/port/in

  • GeoQueryUseCase.java
    Inbound port describing the geolocation queries available to entrypoints (findByIp, findByCity, findByCoordinates).
    Controllers depend on this interface, never on the service implementation directly.

/port/out

  • GeoProviderPort.java
    Outbound (hexagonal) port defining the contract for external geolocation providers.
    Implemented by GeoProviderCompositeAdapter in the infrastructure layer.

/service

  • GeoService.java
    Main application service implementing GeoQueryUseCase. Delegates to GeoProviderPort, manages cache lookups manually via Spring's CacheManager (caches geo-ip, geo-city, geo-coordinates) and signals hits/misses through CacheHitContext.

/cache

  • CacheHitContext.java
    Thread-local flag set by GeoService on every cache access (hit or miss) and read by GeoLocationResponse.from() to populate the cached field returned to clients.

/dto

  • GeoLocationResponse.java
    API-facing response DTO (boundary object), distinct from the domain model and provider DTOs. Includes the cached boolean indicating whether the result was served from cache.

/exception

  • ExternalServiceException.java – thrown when an upstream provider call fails.
  • InvalidInputException.java – thrown for invalid application-level input.
  • GlobalExceptionHandler.java@RestControllerAdvice that converts exceptions into consistent ErrorResponse payloads, ensuring internal details never leak to clients.

3. infrastructure/ — External Integrations (Adapters)

Concrete implementations of the outbound port.
Handles HTTP calls, provider DTOs, mapping, and fallback orchestration.

/adapters

  • GeoProviderCompositeAdapter.java
    Implements GeoProviderPort. Coordinates the primary and fallback provider clients for each operation and maps their results into the domain GeoLocationData:
    • IP lookup: IpGeoClient (ip-api.com) → falls back to IpInfoFallbackClient (ipinfo.io)
    • Reverse geocoding: ReverseGeoClient (Nominatim/OSM) → falls back to BigDataCloudFallbackClient
    • City search: CitySearchClient (Open-Meteo) — no fallback configured

/client

  • client/ip/
    • IpGeoClient.java – primary IP → geolocation provider (ip-api.com)
    • IpInfoFallbackClient.java – fallback IP → geolocation provider (ipinfo.io)
    • dto/IpApiResponse.java, dto/IpInfoResponse.java – provider-specific response DTOs
  • client/reverse/
    • ReverseGeoClient.java – primary reverse-geocoding provider (OSM/Nominatim)
    • BigDataCloudFallbackClient.java – fallback reverse-geocoding provider (BigDataCloud)
    • dto/ReverseGeoResponse.java, dto/BigDataCloudResponse.java – provider-specific response DTOs
  • client/search/
    • CitySearchClient.java – city name → coordinates provider (Open-Meteo)
    • dto/SearchGeoResponse.java – provider-specific response DTO

All clients use RestTemplate (configured in config/AppConfig), translate provider responses into GeoLocationData, and wrap failures in ExternalServiceException so the composite adapter can trigger fallback.


4. presentation/ — HTTP Layer (Controllers, Rate Limiting, Validation, Errors)

Exposes the REST endpoints and handles transport-level concerns only.

/controller

  • GeoController.java
    REST controller for IP lookup, coordinate search, and city lookup (/api/v1/geo/ip/{ip}, /api/v1/geo/coordinates, /api/v1/geo/city/{city}).
    Annotated with @RateLimit per endpoint and @Valid/Bean Validation constraints (@ValidIp, @Min/@Max on coordinates, @Size on city name). Contains no business logic.

/ratelimit

  • RateLimit.java – method-level annotation selecting a RateLimitTier for an endpoint.
  • RateLimitTier.java – enum defining capacity and refill window per tier (IP_LOOKUP: 30 req/min, GEO_SEARCH: 60 req/min, DEFAULT: 60 req/min) and building the corresponding Bucket4j BucketConfiguration.
  • RateLimitService.java – resolves the client identifier (X-Forwarded-For or remote address) and looks up/creates a Bucket4j Bucket per client+tier.
  • RateLimitInterceptor.javaHandlerInterceptor that consumes a token per request, sets X-RateLimit-Limit/X-RateLimit-Remaining headers, and returns 429 Too Many Requests with a Retry-After header and JSON body when the limit is exceeded.
  • WebConfig.java – registers RateLimitInterceptor in the Spring MVC interceptor chain.

/validation

  • ValidIp.java – Bean Validation annotation enforcing valid IP address format.
  • IpValidator.javaConstraintValidator implementation backing @ValidIp.

/error

  • ErrorResponse.java – standardized error payload (timestamp, status, error, message, path) returned by GlobalExceptionHandler for all failure responses.

5. test/ — Complete Test Suite

Combination of unit, integration, and controller tests.

Files & folders:

  • GeoControllerTest.java – Tests the controller layer via MockMvc, including validation and rate-limiting behaviour.
  • GeoServiceTest.java – Unit tests for the application service orchestration logic.
  • GeoServiceCacheTest.java – Verifies cache hit/miss behaviour and CacheHitContext signalling for geo-ip, geo-city and geo-coordinates.
  • GeoProviderCompositeAdapterTest.java – Verifies primary/fallback provider chains and error propagation when all providers fail.
  • IpGeoClientTest.java, ReverseGeoClientTest.java, CitySearchClientTest.java – WireMock-based tests validating provider HTTP integration and DTO mapping.
  • GeoLocateApiApplicationTests.java – Spring context load test.

6. Application Entry

  • GeoLocateApiApplication.java
    The Spring Boot main entry point.

7. config/

  • AppConfig.java – defines the shared RestTemplate bean (Apache HttpClient5-backed) with connection/response timeouts sourced from external.timeout-ms.
  • CacheConfig.java – defines the Caffeine-backed CacheManager with the geo-ip, geo-coordinates and geo-city caches, reading TTL and max-size values from application.yml (cache.*).

Summary

  • domain → core model
  • application → use cases (ports in/out), orchestration service, caching context, DTOs, exceptions
  • infrastructure → provider clients (with fallback variants), DTOs, mappings, composite adapter
  • presentation → controllers, rate limiting, validation, error formatting
  • config → shared beans (HTTP client, cache manager)
  • test → full coverage using MockMvc, WireMock and dedicated cache/fallback test suites

This structure enforces separation of concerns and keeps the system maintainable, testable, and extensible.