Skip to content

Feat/idr-rate-aggregator-cory#155

Open
cory-work-tech wants to merge 23 commits intoallobankdev:mainfrom
cory-work-tech:feat/idr-rate-aggregator
Open

Feat/idr-rate-aggregator-cory#155
cory-work-tech wants to merge 23 commits intoallobankdev:mainfrom
cory-work-tech:feat/idr-rate-aggregator

Conversation

@cory-work-tech
Copy link
Copy Markdown

🏛 Architectural Rationale

1. Polymorphism & Strategy Pattern for Data Fetching

Instead of using conditional blocks (if-else / switch) in the service layer to handle different data resources, the Strategy Pattern (FinancialDataStrategy interface + concrete implementations) was deliberately chosen.

Justification & Benefits:

  • Extensibility
    Adding a new financial data source requires only creating a new class that implements FinancialDataStrategy. No modification needed in StartupDataRunner or other existing strategies → Open/Closed Principle satisfied.

  • Maintainability
    Each strategy is self-contained → encapsulates logic for one resource only. Improves readability, simplifies debugging, and allows isolated unit testing. A growing switch/if-else block would become large, hard to read and error-prone.

  • Separation of Concerns
    High-level algorithm (iterating strategies + storing results in StartupDataRunner) is completely decoupled from the specific fetch/transform logic of each resource.

2. Client Factory: Why FactoryBean<RestTemplate> over plain @Bean?

A FactoryBean<RestTemplate> was implemented instead of a simple @Bean method to encapsulate complex client initialization.

Detailed Reasons:

  • Custom Initialization Control
    FactoryBean allows centralized construction, configuration, and normalization of the RestTemplate in a dedicated class — far beyond what a simple bean method provides.

  • Encapsulation of Complexity
    Handles externalized API base URL (from application.yml) and applies UriTemplateHandler so all strategies automatically benefit from a pre-configured root path.

  • Separation of Concerns
    Decouples the definition of the RestTemplate from the network/configuration logic (timeouts, base paths, interceptors…). Keeps @Configuration classes much cleaner.

  • Proxying & Lifecycle Hook
    FactoryBean integrates deeply into Spring’s bean creation lifecycle — ideal when construction involves significant setup logic that would otherwise clutter configuration classes.

3. Startup Runner: Why ApplicationRunner over @PostConstruct?

ApplicationRunner was chosen (via StartupDataRunner) for initial data ingestion instead of using @PostConstruct methods.

Complete Justification:

  • Context Full Readiness
    @PostConstruct runs during bean initialization — often too early. The full ApplicationContext (proxies, AOP, logging, networking components…) may not be completely ready yet.

  • Access to ApplicationArguments
    ApplicationRunner receives command-line arguments → enables future flexibility (e.g. selective loading via flags).

  • Failure Resilience
    If the external Frankfurter API is unavailable, an exception in @PostConstruct can crash the entire application startup.
    ApplicationRunner executes later → allows graceful error handling so the JVM & application can finish starting even when initial data load fails.

  • Service Availability Guarantee
    Runs only after all beans are created and the application is ready to accept traffic → guarantees InMemoryDataStoreService (and all dependencies) are fully available & properly injected when fetching begins.

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.

2 participants