> For the complete documentation index, see [llms.txt](https://host2host.onibonje.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://host2host.onibonje.com/docs/03-modular-jar-architecture.md).

# Modular JAR Architecture

## 1. Overview

The platform is built as a **composable library platform** with a thin deployable runtime. Capabilities ship as **versioned, reusable JAR modules** (wrapper JARs) that are coupled together at build time. When behavior or integration logic changes, teams update the relevant JAR — not the entire application codebase.

```
┌─────────────────────────────────────────────────────────┐
│  h2h-runtime (deployable Spring Boot application)       │
│  ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────────┐   │
│  │ payments│ │ CBS     │ │  file   │ │ collections │   │
│  │ routes  │ │ provider│ │ adapter │ │   routes    │   │
│  │         │ │(finacle)│ │         │ │             │   │
│       └───────────┴───────────┴─────────────┘           │
│                         │                               │
│              h2h-core-banking-api (BASE)                │
│                  h2h-camel-core                         │
│                  h2h-config-runtime                     │
│                  h2h-common                             │
└─────────────────────────────────────────────────────────┘
```

## 2. Design Goals

| Goal                   | How JAR modules achieve it                                                                                                        |
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| Independent updates    | Bump one module version, rebuild runtime, rolling deploy                                                                          |
| Reuse across countries | Same base CBS library; Finacle provider (or other) per `core_banking_provider_def`                                                |
| Clear boundaries       | Each JAR owns one bounded capability                                                                                              |
| Testability            | Contract tests per module; mock at API boundaries                                                                                 |
| Low-code alignment     | JARs provide step types; database defines which steps run                                                                         |
| Uniform extensibility  | Every library implements `ExtensionProvider` — see [Universal Library Extensibility](/docs/20-universal-library-extensibility.md) |

## 3. Module Categories

### 3.1 Foundation Modules

| Module               | Responsibility                                       |
| -------------------- | ---------------------------------------------------- |
| `h2h-bom`            | Bill of Materials — locks dependency versions        |
| `h2h-common`         | Shared models, error codes, correlation ID utilities |
| `h2h-config-api`     | Configuration interfaces and DTOs (no database)      |
| `h2h-config-store`   | JPA entities, repositories, Flyway migrations        |
| `h2h-config-runtime` | Config cache, resolver, publish event handling       |

### 3.2 Cross-Cutting Modules

| Module                        | Responsibility                                                                                               |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------ |
| `h2h-camel-core`              | Idempotency, audit, retry, DLQ, error handlers                                                               |
| `h2h-security`                | Vault client, PGP operations, credential resolution                                                          |
| `h2h-core-banking-api`        | **Base library** — `CoreBankingIntegration`, CBS DTOs, `CoreBankingOperationProvider` SPI, provider registry |
| `h2h-workflow-api`            | `ApprovalService`, maker–checker contracts (no Camunda dependency)                                           |
| `h2h-workflow-camunda`        | Camunda engine adapter, multi-level approval, `camunda:` Camel component                                     |
| `h2h-notification-api`        | `NotificationService`, `NotificationProvider` SPI                                                            |
| `h2h-notification-dispatcher` | Event-driven delivery, templates, recipient resolution                                                       |

### 3.3 Adapter / Wrapper Modules

| Module                   | Wraps                                                           | Exposes                                                |
| ------------------------ | --------------------------------------------------------------- | ------------------------------------------------------ |
| `h2h-finacle-wrapper`    | **CBS provider: Finacle** — implements `CoreBankingIntegration` | `finacle:` / `corebank:` Camel component               |
| `h2h-file-adapter`       | SFTP, local file system, archiving                              | `file:` / `sftp:` enhanced components                  |
| `h2h-http-ingress`       | REST/SOAP HTTP sync                                             | `platform-http:`, `cxf:` — paths from `channel_config` |
| `h2h-websocket-ingress`  | WebSocket real-time push                                        | WSS sessions, `EventWebSocketDispatcher`               |
| `h2h-mq-adapter`         | Kafka, JMS                                                      | `kafka:` producers/consumers with standard headers     |
| `h2h-transform-iso20022` | ISO 20022 parsing and mapping                                   | `transform:iso20022` component                         |
| `h2h-transform-mt940`    | SWIFT MT940/942                                                 | `transform:mt940` component                            |
| `h2h-ack-nack`           | Acknowledgement generation                                      | `ack-nack:` component                                  |

### 3.4 Route Modules (Orchestration)

| Module                   | Responsibility                    |
| ------------------------ | --------------------------------- |
| `h2h-payments-routes`    | Bulk payment STP flows            |
| `h2h-collections-routes` | Collection and direct debit flows |
| `h2h-statements-routes`  | Statement generation and delivery |
| `h2h-reconciliation`     | Reconciliation matching pipelines |

### 3.5 Regional / Optional Modules

| Module          | Responsibility                                                          |
| --------------- | ----------------------------------------------------------------------- |
| `h2h-routes-ng` | Nigeria-specific step extensions (only if regulation requires new code) |
| `h2h-routes-gh` | Ghana-specific extensions                                               |
| `h2h-admin-api` | REST APIs for low-code admin portal                                     |

### 3.6 Runtime Shell

| Module        | Responsibility                                                                                             |
| ------------- | ---------------------------------------------------------------------------------------------------------- |
| `h2h-runtime` | Spring Boot application — composes enabled JARs; packaged as **executable JAR**, **WAR**, or **OCI image** |

### 3.7 Core Banking Base Library vs CBS Providers

```mermaid
flowchart TB
  subgraph base [h2h-core-banking-api — BASE LIBRARY]
    IF[CoreBankingIntegration]
    DTO[Canonical CBS DTOs]
    SPI[CoreBankingOperationProvider]
    REG[CoreBankingProviderRegistry]
  end

  subgraph providers [CBS Provider Types — pluggable JARs]
    FIN[h2h-finacle-wrapper FINACLE]
    MOCK[h2h-cbs-mock]
    OTHER[h2h-cbs-vendor future]
  end

  subgraph routes [Route Modules]
    PAY[h2h-payments-routes]
    COLL[h2h-collections-routes]
  end

  PAY --> IF
  COLL --> IF
  FIN -.->|implements| IF
  MOCK -.->|implements| IF
  OTHER -.->|implements| IF
  REG --> FIN
  REG --> MOCK
  REG --> OTHER
```

**Rule:** Route modules Maven-depend on `h2h-core-banking-api` only. CBS provider JARs are runtime composition dependencies.

### 3.8 Deployment packaging (same JARs)

| Packaging      | Module profile | Target                                    |
| -------------- | -------------- | ----------------------------------------- |
| Executable JAR | `boot-jar`     | VM, systemd, legacy DC without containers |
| WAR            | `war`          | WebLogic, WebSphere, JBoss EAP            |
| OCI image      | `docker`       | Kubernetes / OpenShift (optional)         |

See [19 Cloud-Agnostic Deployment](/docs/19-cloud-agnostic-deployment.md) — deployment is **not Docker-only**.

## 4. Wrapper JAR Internal Structure

Every wrapper JAR follows a consistent package layout. **Core banking** splits interface (API module) from Finacle implementation (wrapper module):

```
h2h-core-banking-api/
├── src/main/java/com/heirs/h2h/corebanking/api/
│   ├── CoreBankingIntegration.java      # Stable CBS contract
│   ├── CoreBankingContext.java
│   ├── CoreBankingOperationProvider.java
│   └── package-info.java

h2h-finacle-wrapper/
├── src/main/java/com/heirs/h2h/finacle/
│   ├── adapter/                         # FinacleCoreBankingIntegration implements CoreBankingIntegration
│   ├── internal/                        # FCJ/FCUBS clients (private)
│   │   ├── FcjClient.java
│   │   ├── FcubsClient.java
│   │   └── FinacleConnectionPool.java
│   ├── camel/                           # finacle: component — injects CoreBankingIntegration
│   │   ├── FinacleComponent.java
│   │   ├── FinacleEndpoint.java
│   │   └── FinacleProducer.java
│   └── config/
│       └── FinacleAutoConfiguration.java
└── src/test/java/
```

**Legacy note:** `FinacleService` in older drafts is superseded by `CoreBankingIntegration`. The Finacle wrapper registers `FinacleCoreBankingIntegration` as the `CoreBankingIntegration` bean.

### 4.1 Public API Rules

* **Stable:** Breaking changes require MAJOR version bump
* **Minimal:** Expose only what route modules need
* **Technology-agnostic:** DTOs do not leak Finacle SDK types

### 4.2 Internal Package Rules

* FCJ/FCUBS SDK calls stay in `internal`
* Connection pooling, circuit breakers, timeouts are internal concerns
* No other module imports `internal` packages (enforce with ArchUnit)

## 5. Auto-Configuration Pattern

Each JAR registers itself via Spring Boot auto-configuration:

```java
@AutoConfiguration
@ConditionalOnProperty(name = "h2h.modules.payments.enabled", havingValue = "true")
public class PaymentsRoutesAutoConfiguration {

    @Bean
    public RouteBuilder bulkPaymentRouteBuilder(
            ConfigResolver configResolver,
            CoreBankingIntegration coreBanking) {
        return new BulkPaymentRouteBuilder(configResolver, coreBanking);
    }
}
```

Registration in `META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports`:

```
com.heirs.h2h.payments.config.PaymentsRoutesAutoConfiguration
```

### 5.1 Module Enablement

```yaml
# application.yml — infrastructure only, NOT partner config
h2h:
  modules:
    payments:
      enabled: true
    collections:
      enabled: true
    statements:
      enabled: false
  country: NG
  environment: production
```

## 6. Composition in the Runtime

The runtime `pom.xml` declares which capability JARs to include:

```xml
<dependencies>
    <!-- Foundation -->
    <dependency>
        <groupId>com.heirs.h2h</groupId>
        <artifactId>h2h-camel-core</artifactId>
    </dependency>
    <dependency>
        <groupId>com.heirs.h2h</groupId>
        <artifactId>h2h-config-runtime</artifactId>
    </dependency>

    <!-- Adapters -->
    <dependency>
        <groupId>com.heirs.h2h</groupId>
        <artifactId>h2h-finacle-wrapper</artifactId>
    </dependency>
    <dependency>
        <groupId>com.heirs.h2h</groupId>
        <artifactId>h2h-file-adapter</artifactId>
    </dependency>

    <!-- Routes -->
    <dependency>
        <groupId>com.heirs.h2h</groupId>
        <artifactId>h2h-payments-routes</artifactId>
    </dependency>
</dependencies>
```

The runtime contains **no business logic** — only:

* Spring Boot main class
* Infrastructure configuration (DB connection, Kafka brokers)
* Module enablement flags
* Health checks and actuator endpoints

## 7. Dependency Rules

```mermaid
flowchart BT
  RUNTIME[h2h-runtime]
  ROUTES[route modules]
  ADAPTERS[adapter modules]
  CORE[h2h-camel-core]
  CONFIG[h2h-config-runtime]
  COMMON[h2h-common]

  RUNTIME --> ROUTES
  RUNTIME --> ADAPTERS
  RUNTIME --> CORE
  RUNTIME --> CONFIG
  ROUTES --> ADAPTERS
  ROUTES --> CORE
  ROUTES --> CONFIG
  ADAPTERS --> COMMON
  CORE --> CONFIG
  CONFIG --> COMMON
```

**Forbidden:**

* Adapter modules depending on route modules
* Circular dependencies between any modules
* Route modules importing adapter `internal` packages
* Any module depending on `h2h-runtime`

## 8. Versioning Strategy

### 8.1 Semantic Versioning

| Bump  | When                                            |
| ----- | ----------------------------------------------- |
| MAJOR | Breaking public API change                      |
| MINOR | New feature, new step type, backward compatible |
| PATCH | Bug fix, performance improvement                |

### 8.2 Example Version Matrix

| Module                | Version | Notes                        |
| --------------------- | ------- | ---------------------------- |
| `h2h-bom`             | 1.4.0   | Defines compatible set       |
| `h2h-finacle-wrapper` | 2.1.0   | New FCUBS operation added    |
| `h2h-payments-routes` | 1.8.2   | Bug fix in split handling    |
| `h2h-runtime`         | 1.4.0   | Repackages BOM 1.4.0 modules |

### 8.3 Update Workflow

```
1. Developer fixes bug in h2h-finacle-wrapper
2. Bump version: 2.1.0 → 2.1.1
3. Publish to Artifactory
4. Update h2h-bom to reference 2.1.1
5. Rebuild h2h-runtime (no route changes needed)
6. CI builds Docker image
7. Rolling deploy to Kubernetes
```

**No changes required** in payments-routes or admin portal for wrapper-only fixes.

## 9. Custom Camel Components

Wrapper JARs may expose Camel components for clean route DSL:

| Component URI         | Module            | Example                      |
| --------------------- | ----------------- | ---------------------------- |
| `finacle:postPayment` | finacle-wrapper   | `.to("finacle:postPayment")` |
| `crypto:pgpDecrypt`   | security          | `.to("crypto:pgpDecrypt")`   |
| `transform:apply`     | transform modules | `.to("transform:apply")`     |
| `idempotent:check`    | camel-core        | `.to("idempotent:check")`    |
| `ack-nack:generate`   | ack-nack          | `.to("ack-nack:generate")`   |

Component implementations read partner-specific details from `ConfigResolver`, not from URI parameters hardcoded in routes.

## 10. Country Packs

Prefer **database configuration** over country JARs. Create country route JARs only when:

* A new Camel step type is required (new `Processor` bean)
* Regulatory mandate cannot be expressed as config/rules
* Finacle service variant requires code-level handling

Country packs follow naming: `h2h-routes-{country-code}`.

Enable via module flags:

```yaml
h2h:
  modules:
    routes-ng:
      enabled: true
```

## 11. Testing Strategy per Module

| Module Type | Test Approach                                               |
| ----------- | ----------------------------------------------------------- |
| Wrapper     | Unit tests with mocked SDK; contract tests publish API spec |
| Camel core  | Camel Test Kit with mock endpoints                          |
| Routes      | Route tests with Testcontainers (DB, Kafka)                 |
| Config      | Repository tests; resolver cache invalidation tests         |
| Runtime     | Smoke test — context starts with all modules enabled        |

### 11.1 Contract Tests

`h2h-finacle-wrapper` publishes test fixtures:

```
src/test/resources/contracts/post-payment-success.json
src/test/resources/contracts/post-payment-insufficient-funds.json
```

Route modules consume these in integration tests to verify compatibility.

## 12. Anti-Patterns

| Anti-Pattern                                     | Correct Approach                  |
| ------------------------------------------------ | --------------------------------- |
| Partner-specific `if` statements in wrapper JARs | Database-driven config            |
| God module with all routes                       | Separate route modules per domain |
| Shared mutable static state                      | Spring beans, exchange properties |
| Copy-paste retry logic per route                 | Centralize in `h2h-camel-core`    |
| Different Camel versions per module              | Lock via `h2h-bom`                |
| Storing secrets in wrapper config                | Vault references only             |

## 13. Future: Plugin Loading (Optional)

For advanced scenarios, consider **PF4J** for dynamic route plugin loading in non-production environments. Production should continue with **versioned JAR composition + rolling deploy** for auditability and simplicity.

## 14. Related Documents

* [Design Patterns](/docs/13-design-patterns.md)
* [Universal Library Extensibility](/docs/20-universal-library-extensibility.md)
* [Extensibility Framework](/docs/14-extensibility-framework.md)
* [Camel Integration Patterns](/docs/08-camel-integration-patterns.md)
* [Repository Structure](/docs/11-repository-structure.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://host2host.onibonje.com/docs/03-modular-jar-architecture.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
