Skip to content

feat: implement IDR rate aggregator with strategy pattern and startup preloading#217

Open
joniheri wants to merge 6 commits into
allobankdev:mainfrom
joniheri:feat/idr-rate-aggregator
Open

feat: implement IDR rate aggregator with strategy pattern and startup preloading#217
joniheri wants to merge 6 commits into
allobankdev:mainfrom
joniheri:feat/idr-rate-aggregator

Conversation

@joniheri
Copy link
Copy Markdown

Summary

This PR implements a Spring Boot REST API that aggregates Indonesian Rupiah (IDR) exchange data from the Frankfurter API.

The application exposes a single polymorphic endpoint and preloads all required data at startup into an in-memory store. It ensures no external API calls are made during request handling.

Key Features

  • Single endpoint: /api/finance/data/{resourceType}

  • Supports:

    • latest_idr_rates
    • historical_idr_usd
    • supported_currencies
  • Custom spread calculation for latest_idr_rates

  • Thread-safe and immutable in-memory data store

  • No external API calls during runtime requests


Architectural Rationale

1. Strategy Pattern

The Strategy Pattern is used to handle multiple resource types without relying on conditional branching such as if-else or switch.

Each resource type is encapsulated in its own strategy class (LatestIdrRatesFetcher, HistoricalIdrUsdFetcher, SupportedCurrenciesFetcher). This design improves extensibility, maintainability, and testability. New resource types can be added without modifying existing logic.


2. Client FactoryBean

A custom FactoryBean is used to construct the HTTP client (RestTemplate). This ensures that all client configuration (such as base URL and timeouts) is centralized and externalized via application.yml.

This approach avoids tight coupling between business logic and infrastructure concerns, and aligns with Spring’s inversion of control principles.


3. ApplicationRunner

ApplicationRunner is used to preload all required data during application startup.

This ensures:

  • External API is called only once
  • All data is available before serving requests
  • Improved runtime performance by avoiding repeated API calls

Compared to alternatives like @PostConstruct, ApplicationRunner provides better control over application lifecycle and initialization timing.


Personalization

  • GitHub Username: joniheri
  • Spread Factor: 0.00856

The latest_idr_rates response includes a custom calculated field:

USD_buy_spread_IDR = (1 / Rate_USD) * (1 + Spread_Factor)

How to Test

mvn spring-boot:run

curl http://localhost:8080/api/finance/data/latest_idr_rates
curl http://localhost:8080/api/finance/data/historical_idr_usd
curl http://localhost:8080/api/finance/data/supported_currencies

… immutable store

- add Strategy-based fetchers for latest rates, historical USD/IDR, and supported currencies
- preload external finance data once at startup via ApplicationRunner
- store data in thread-safe immutable in-memory store
- expose /api/finance/data/{resourceType} endpoint with global exception handling
- add RestTemplate FactoryBean config, OpenAPI setup, unit tests, and Postman collection
- refine strategy fetchers and service/controller data path
- improve preload runner and immutable in-memory store behavior
- update README and add/adjust unit + integration tests for runner/strategies
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant