Layer 5 — Integration Services: Spring Boot
Multiple external system adapters. One dedicated Spring Boot service each. Every failure is recoverable.
Table of Contents
8.1 Design: One Adapter Per System Boundary
Anchita uses a set of dedicated Spring Boot integration adapters — one per external system family — rather than a shared integration gateway:
integration-service/
├── core-banking-adapter/ — Core Banking System (customer, account lookup)
├── treasury-platform-adapter/ — Treasury Management Platform (entitlements)
├── wire-transfer-adapter/ — Wire Transfer System (profiles, accounts)
├── anchita-portal-adapter/ — Anchita Digital Banking Portal (all segments; tier-based feature gating)
├── document-mgmt-adapter/ — Document Management System
├── directory-auth-adapter/ — Directory Authentication Service (LDAP)
├── token-auth-adapter/ — Token Authentication System (MFA tokens)
├── rtp-network-adapter/ — Instant Payments Network
├── payment-processing-adapter/ — Payment Processing Platform (Bill Pay)
├── financial-data-adapter/ — Financial Data Service (Bill Pay user)
└── [remaining adapters...]
Each adapter is independently deployable — failures in one adapter do not affect other adapters. This avoids the single point of failure that a shared integration gateway would represent.
8.2 Adapter Pattern
Each adapter follows the same Spring Boot pattern with Resilience4j circuit breaker and retry:
@Service
public class CoreBankingAdapter {
private final RestClient restClient;
private final CircuitBreaker circuitBreaker; // Resilience4j
@Retry(name = "coreBanking", fallbackMethod = "fallbackLookup")
@CircuitBreaker(name = "coreBanking")
public CompanyRecord lookupCompany(String customerId) {
return restClient.get()
.uri("/api/v2/customers/{id}", customerId)
.retrieve()
.body(CompanyRecord.class);
}
private CompanyRecord fallbackLookup(String customerId, Exception ex) {
// Throw ApplicationFailure → Temporal retries or routes to error recovery
throw ApplicationFailure.newFailure(
"Core Banking lookup failed: " + ex.getMessage(),
"INTEGRATION_FAILURE"
);
}
}
Resilience Pattern (per adapter)
| Mechanism | Configuration | Behaviour |
|---|---|---|
| Circuit breaker (Resilience4j) | Opens after 5 consecutive failures; half-open after 30s | Prevents cascading failures; fails fast when the downstream is down |
| Retry (Temporal built-in) | Up to 3 attempts with exponential backoff | Handles transient network failures transparently |
| Dead letter | After all retries exhausted → ApplicationFailure |
Temporal routes to the error recovery signal; operator is notified |
| Activity timeout | 30s default, configurable per system | Prevents indefinite blocking on a slow downstream |
This chain means: transient failures are automatically retried; persistent failures surface to the operator as an actionable error recovery task in the React workspace, with the error message and recommended action.
8.3 OpenAPI Contract Strategy
Each external system has an OpenAPI 3.0 YAML spec in the repository. These are the same contracts used in the mock/test environment and production — only the base URL changes:
# core-banking-api.yaml
openapi: 3.0.0
info:
title: Core Banking System API
version: 2.0.0
paths:
/customers/{customerId}:
get:
summary: Retrieve customer profile
parameters:
- name: customerId
in: path
required: true
schema:
type: string
responses:
'200':
description: Customer profile
content:
application/json:
schema:
$ref: '#/components/schemas/CompanyRecord'
/accounts/{accountId}:
get:
summary: Retrieve account details
Spring Boot generates typed client stubs from these specs using openapi-generator-maven-plugin. This means:
- The adapter code never uses raw strings for request/response fields
- Schema changes in the spec break the build immediately — not at runtime
- The same spec can be used to generate mock servers for integration testing
- Contract documentation is always in sync with the implementation
Contract-first design: Each external system integration starts with an OpenAPI 3.0 spec. Spring Boot generates typed client stubs from the spec — the contract is the source of truth, and the same spec governs both mock/test environments and production.