Skip to main content

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

AreaTechnologyVersion
LanguageJava21
FrameworkSpring Boot3.5.14
EventingSpring Cloud Stream (Kafka binder) + Spring Cloud FunctionSpring Cloud 2025.0.2
IntegrationApache Camel4.18.2
Enterprise MQIBM MQ via JMS (mq-jms-spring-boot-starter)3.5.13
SWIFT SDKProwide (pw-swift-core, pw-iso20022, integrator)SRU2025
AWSSpring Cloud AWS / SDK v2 (DynamoDB, S3, SQS, Bedrock)3.4.2 / 2.46.5
GenAISpring AI + AWS Bedrock (Claude)1.1.7
Cross-borderMastercard client-encryption + oauth1-signer1.8.8 / 1.6.0
WorkflowsNetflix/Orkes Conductor client4.1.3
ObservabilityOpenTelemetry (OTLP) + Micrometer tracing; Jaeger; Seq
ImagesJib → 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.

ModuleResponsibility
afpay-message-commonShared library — Camel route builders, Kafka idempotent repo, DynamoDB/JAXB config, ISO/MX converters, domain models
afpay-message-processorCore Camel router — consumes SWIFT MT/ISO from IBM MQ, fans out to CBS / TMS / SAP and back to SWIFT
afpay-message-translationMT ↔ MX (ISO 20022) conversion via Prowide
afpay-message-crossborderCross-border payments — MT103 → Mastercard RemittanceRequest (OAuth1-signed + encrypted), SQS, circuit breakers
afpay-message-aitoolsShared GenAI library — AWS Bedrock (Claude) address restructuring
afpay-message-trackerSWIFT GPI tracking — Oracle (JPA), Conductor workflows, MT199 status
afpay-message-sftpSFTP ingress/egress — Redis dedup, Quartz retry, S3 fallback
afpay-message-emergencyLightweight fallback SFTP handler when primary systems fail
afpay-message-managerSanctions / screening orchestration (AfpayScreeningApplication)
afpay-message-archivePersists processed messages to DynamoDB; bridges to warehouse/statement queues
afpay-message-dlqDead-letter sink — DynamoDB persistence + Jira ticketing
crossborder-webhook-lambdaSeparate 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

  1. 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.
  2. Process — Camel RouteBuilders (destinations injected from application-bindings.yml, never hard-coded) screen (sanctions/fraud), translate MT↔ISO, and route.
  3. Fan-out — to CBS (CBS.MT.IN.*), TMS, SAP/ERP, fraud screening, and back to SWIFT (SWIFT.IN.ISO / SWIFT.IN.MT).
  4. Cross-border — MT103 → Mastercard RemittanceRequest with AI-assisted address cleanup (Bedrock/Claude).
  5. Sinks — archive (DynamoDB + warehouse/statement queues), GPI tracking (Oracle + Conductor), and on failure the MESSAGE.HUB.EXCEPTION.DLQafpay-message-dlq (DynamoDB + Jira, with replay).
  6. 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 local brings up Redis, IBM MQ, LocalStack (s3/sqs/lambda/dynamodb), Seq, Postgres, Jaeger, and Redpanda (Kafka) + console; make mq and make conductor for those subsystems.
  • CI/CD — two Jenkins pipelines: Jenkinsfile builds and pushes images (per-service gradle :svc:jib), Jenkinsfile.ecs deploys via aws ecs update-service --force-new-deployment against the Integration cluster 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. :::