Architecture
An event-driven choreography of ~11 Spring Boot microservices over a Spring Cloud Stream + Apache Kafka backbone, with IBM MQ (JMS) for enterprise queues and Apache Camel for routing.
Tech stack
| Area | Technology | Version |
|---|---|---|
| Language | Java | 21 |
| Framework | Spring Boot | 3.5.14 |
| Eventing | Spring Cloud Stream (Kafka binder) + Spring Cloud Function | Spring Cloud 2025.0.2 |
| Integration | Apache Camel | 4.18.2 |
| Enterprise MQ | IBM MQ via JMS (mq-jms-spring-boot-starter) | 3.5.13 |
| SWIFT SDK | Prowide (pw-swift-core, pw-iso20022, integrator) | SRU2025 |
| AWS | Spring Cloud AWS / SDK v2 (DynamoDB, S3, SQS, Bedrock) | 3.4.2 / 2.46.5 |
| GenAI | Spring AI + AWS Bedrock (Claude) | 1.1.7 |
| Cross-border | Mastercard client-encryption + oauth1-signer | 1.8.8 / 1.6.0 |
| Workflows | Netflix/Orkes Conductor client | 4.1.3 |
| Observability | OpenTelemetry (OTLP) + Micrometer tracing; Jaeger; Seq | — |
| Images | Jib → AWS ECR (eu-west-1) | 3.5.3 |
Modules
Buildable modules (from settings.gradle); each is its own Spring Boot app
(Afpay*Application) unless noted.
| Module | Responsibility |
|---|---|
afpay-message-common | Shared library — Camel route builders, Kafka idempotent repo, DynamoDB/JAXB config, ISO/MX converters, domain models |
afpay-message-processor | Core Camel router — consumes SWIFT MT/ISO from IBM MQ, fans out to CBS / TMS / SAP and back to SWIFT |
afpay-message-translation | MT ↔ MX (ISO 20022) conversion via Prowide |
afpay-message-crossborder | Cross-border payments — MT103 → Mastercard RemittanceRequest (OAuth1-signed + encrypted), SQS, circuit breakers |
afpay-message-aitools | Shared GenAI library — AWS Bedrock (Claude) address restructuring |
afpay-message-tracker | SWIFT GPI tracking — Oracle (JPA), Conductor workflows, MT199 status |
afpay-message-sftp | SFTP ingress/egress — Redis dedup, Quartz retry, S3 fallback |
afpay-message-emergency | Lightweight fallback SFTP handler when primary systems fail |
afpay-message-manager | Sanctions / screening orchestration (AfpayScreeningApplication) |
afpay-message-archive | Persists processed messages to DynamoDB; bridges to warehouse/statement queues |
afpay-message-dlq | Dead-letter sink — DynamoDB persistence + Jira ticketing |
crossborder-webhook-lambda | Separate Quarkus / AWS Lambda stack — inbound cross-border status webhooks → SQS |
:::note Snapshot caveats
afpay-message-saa (SWIFT Alliance Access) and afpay-message-observability
exist only as stale build artifacts (no src/, not in settings.gradle) in this
snapshot — the SAA function lives on as IBM MQ ingestion inside
afpay-message-processor. The k8s/ directory is empty; deployment is ECS.
:::
Message flow
- Inbound — IBM MQ / JMS is the primary mission-critical ingress (SWIFT Alliance Access feed); SFTP for file-based flows; Kafka between services; a Quarkus Lambda receives cross-border webhooks → SQS.
- Process — Camel
RouteBuilders (destinations injected fromapplication-bindings.yml, never hard-coded) screen (sanctions/fraud), translate MT↔ISO, and route. - Fan-out — to CBS (
CBS.MT.IN.*), TMS, SAP/ERP, fraud screening, and back to SWIFT (SWIFT.IN.ISO/SWIFT.IN.MT). - Cross-border — MT103 → Mastercard
RemittanceRequestwith AI-assisted address cleanup (Bedrock/Claude). - Sinks — archive (DynamoDB + warehouse/statement queues), GPI tracking
(Oracle + Conductor), and on failure the
MESSAGE.HUB.EXCEPTION.DLQ→afpay-message-dlq(DynamoDB + Jira, with replay). - Idempotency — three layers: Kafka idempotent repository, Redis file-level dedup (SFTP), and DynamoDB UUID + auto-versioning.
SWIFT / standards
- SWIFT MT — MT103, MT202, MT199 (parsed/built with Prowide
pw-swift-core). - ISO 20022 (MX) via Prowide
pw-iso20022+ JAXB — pacs (008/009/010/004/003/002), pain (001/002/008), and the camt family (052/053/054/055/056/057/058/060/029/…). - BIC directory lookups via Apache Derby; LAU signatures on v2 XML wrappers.
- Prowide CBPR+ / SIC / SCORE integrator libraries are bundled.
Build & deploy
- Gradle multi-module, root wrapper; Spring Boot + Jib applied to every
module with a
src/. Prowide JARs are vendored under/libs. No test suite in this snapshot. - Jib images → AWS ECR (
eu-west-1), BellSoft Liberica JRE 21 base. - Local dev via
docker/Makefile:make localbrings up Redis, IBM MQ, LocalStack (s3/sqs/lambda/dynamodb), Seq, Postgres, Jaeger, and Redpanda (Kafka) + console;make mqandmake conductorfor those subsystems. - CI/CD — two Jenkins pipelines:
Jenkinsfilebuilds and pushes images (per-servicegradle :svc:jib),Jenkinsfile.ecsdeploys viaaws ecs update-service --force-new-deploymentagainst theIntegrationcluster using pinned task-definition ARNs.
:::note No service-level OpenAPI
The hub is event-driven, not a REST service, so it has no published API
reference. The OpenAPI/Swagger files in afpay-message-crossborder are
inputs to SDK generation (Mastercard cross-border, address/account
validation) — third-party contracts, not this hub's own API.
:::