> 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/18-execution-context.md).

# Execution Context Framework

## 1. Overview

The **Execution Context Framework** (`h2h-context`) provides a unified, immutable **request-scoped context** that flows through every layer of the H2H platform — Camel routes, services, scripts, jobs, audit, logging, and tracing. It answers: *who is this transaction for, what config applies, and how do we trace it end-to-end?*

**Module:** `h2h-context`

**Package root:** `com.heirs.h2h.context`

Without a consistent context model, correlation IDs get lost, partner config is re-fetched repeatedly, and audit trails break. This library is the **single source of truth** for execution-scoped state.

```mermaid
flowchart TB
  subgraph ingress [Ingress]
    SFTP[SFTP Poll]
    API[API Request]
    Kafka[Kafka Message]
  end

  subgraph context [h2h-context]
    Builder[H2hContextBuilder]
    Holder[H2hContextHolder]
    Propagator[ContextPropagator]
  end

  subgraph consumers [Consumers]
    Camel[Camel Exchange]
    MDC[SLF4J MDC]
    OTel[OpenTelemetry Span]
    Audit[Audit Events]
    Scripts[Script Engine]
    Jobs[Job Executor]
  end

  ingress --> Builder
  Builder --> Holder
  Holder --> Camel
  Holder --> MDC
  Holder --> OTel
  Holder --> Audit
  Holder --> Scripts
  Propagator --> Kafka
```

***

## 2. Design Principles

| Principle                         | Implementation                                        |
| --------------------------------- | ----------------------------------------------------- |
| Immutable context                 | `H2hContext` is a record — no mutation after creation |
| Create once, enrich incrementally | Builder pattern; new instance per enrichment          |
| Propagate everywhere              | Camel properties, MDC, Kafka headers, HTTP headers    |
| No global mutable state           | `ThreadLocal` holder cleared after request            |
| Context carries config snapshot   | Resolved `IntegrationProfile` attached — no re-fetch  |
| Async-safe                        | Context passed explicitly to async tasks              |

***

## 3. H2hContext Model

### 3.1 Core Context Record

```java
public record H2hContext(
    // Identity
    String correlationId,
    String partnerId,
    String countryCode,
    String messageType,
    String environment,

    // Batch / file
    String batchId,
    String fileId,
    String originalFilename,

    // Resolved configuration (snapshot at resolution time)
    IntegrationProfile profile,
    String configVersion,

    // Processing state
    String status,
    String currentStep,
    int stepIndex,
    boolean duplicate,

    // Tracing
    String traceId,
    String spanId,

    // Timestamps
    Instant startedAt,

    // Extensible metadata
    Map<String, String> attributes
) {}
```

### 3.2 Context Fields Reference

| Field                | Set when                       | Used by                                 |
| -------------------- | ------------------------------ | --------------------------------------- |
| `correlationId`      | Ingress (generate or extract)  | Logs, traces, audit, partner status API |
| `partnerId`          | Partner identification step    | Config resolution, RBAC, metrics tags   |
| `countryCode`        | From partner record            | Routing, SLA, holiday calendar          |
| `messageType`        | File pattern / API path        | Profile resolution                      |
| `environment`        | Runtime config                 | Sandbox vs production isolation         |
| `batchId`            | File ingest / API batch header | Batch aggregation, ACK                  |
| `fileId`             | File registry registration     | File management, delivery               |
| `profile`            | Config resolution              | All pipeline steps                      |
| `configVersion`      | Config resolution              | Audit — which config version was active |
| `status`             | Updated by processors          | Lifecycle tracking, ops dashboard       |
| `currentStep`        | Step executor                  | Error reporting, audit                  |
| `traceId` / `spanId` | Observability start            | Distributed tracing                     |
| `attributes`         | Any step                       | Custom key-value pairs                  |

***

## 4. Context Lifecycle

```mermaid
stateDiagram-v2
  [*] --> CREATED: Ingress event
  CREATED --> IDENTIFIED: Partner + message type known
  IDENTIFIED --> RESOLVED: IntegrationProfile loaded
  RESOLVED --> PROCESSING: Pipeline executing
  PROCESSING --> COMPLETED: Success
  PROCESSING --> FAILED: Error
  PROCESSING --> DUPLICATE: Idempotency hit
  COMPLETED --> [*]
  FAILED --> [*]
  DUPLICATE --> [*]
```

### 4.1 Creation Points

| Ingress            | Correlation ID source                               |
| ------------------ | --------------------------------------------------- |
| SFTP file poll     | Generated UUID (or extracted from filename pattern) |
| API request        | `X-Correlation-Id` header (required or generated)   |
| Kafka message      | `correlationId` Kafka header                        |
| Broker-delayed job | Generated UUID per job execution                    |

***

## 5. H2hContextBuilder

```java
public class H2hContextBuilder {

    public static H2hContextBuilder create() { ... }

    public H2hContextBuilder correlationId(String id);

    public H2hContextBuilder partnerId(String id);

    public H2hContextBuilder fromExchange(Exchange exchange);

    public H2hContextBuilder fromHttpHeaders(HttpHeaders headers);

    public H2hContextBuilder fromKafkaRecord(ConsumerRecord<?, ?> record);

    public H2hContextBuilder withProfile(IntegrationProfile profile);

    public H2hContextBuilder withStatus(String status);

    public H2hContextBuilder attribute(String key, String value);

    public H2hContext build();
}
```

**Immutability:** Each `with*` method returns a **new builder** copying previous state.

***

## 6. H2hContextHolder

Thread-local holder for the current context within a processing thread.

```java
public final class H2hContextHolder {

    public static void set(H2hContext context);

    public static H2hContext get();

    public static H2hContext require();  // throws if missing

    public static void clear();          // MUST call in finally block
}
```

### 6.1 Usage Pattern

```java
try {
    H2hContextHolder.set(context);
    MdcContextPropagator.apply(context);
    // ... processing ...
} finally {
    H2hContextHolder.clear();
    MDC.clear();
}
```

**Critical:** Always clear in `finally` — Camel thread pool reuse will leak context otherwise.

***

## 7. Camel Exchange Integration

### 7.1 Exchange Property Convention

Context is stored on the Camel exchange as a single property:

```java
exchange.setProperty("h2h.context", context);
```

Individual fields are **also** set for backward compatibility and Camel simple expressions:

| Property            | Field                     |
| ------------------- | ------------------------- |
| `h2h.correlationId` | `context.correlationId()` |
| `h2h.partnerId`     | `context.partnerId()`     |
| `h2h.profile`       | `context.profile()`       |
| `h2h.status`        | `context.status()`        |
| `h2h.batchId`       | `context.batchId()`       |
| `h2h.fileId`        | `context.fileId()`        |

### 7.2 ContextProcessor

Central processor that builds/updates context on the exchange:

```java
@Component
public class ContextProcessor implements Processor {

  @Override
  public void process(Exchange exchange) {
    H2hContext existing = exchange.getProperty("h2h.context", H2hContext.class);
    H2hContext updated = H2hContextBuilder.from(existing)
        .withStatus("PROCESSING")
        .build();
    applyToExchange(exchange, updated);
    H2hContextHolder.set(updated);
  }
}
```

### 7.3 Route Entry Pattern

```java
from("file-mgmt:poll")
    .process(contextInitProcessor)       // Create H2hContext
    .process(partnerIdentifyProcessor)   // Set partnerId, messageType
    .process(configResolverProcessor)    // Attach profile
    .process(contextProcessor)           // Update exchange + holder
    .to("direct:execute-profile");
```

***

## 8. Context Propagation

### 8.1 ContextPropagator API

```java
public interface ContextPropagator {

    void toMdc(H2hContext context);

    void toExchange(Exchange exchange, H2hContext context);

    void toKafkaHeaders(ProducerRecord<?, ?> record, H2hContext context);

    H2hContext fromKafkaHeaders(ConsumerRecord<?, ?> record);

    void toHttpHeaders(HttpHeaders headers, H2hContext context);

    H2hContext fromHttpHeaders(HttpHeaders headers);
}
```

### 8.2 Propagation Matrix

| Boundary      | Mechanism          | Headers / properties                              |
| ------------- | ------------------ | ------------------------------------------------- |
| HTTP inbound  | `fromHttpHeaders`  | `X-Correlation-Id`, `X-Partner-Id`, `traceparent` |
| HTTP outbound | `toHttpHeaders`    | Same                                              |
| Kafka produce | `toKafkaHeaders`   | `correlationId`, `partnerId`, `traceparent`       |
| Kafka consume | `fromKafkaHeaders` | Rebuild `H2hContext`                              |
| Camel async   | Exchange property  | `h2h.context` serialized on exchange              |
| Thread pool   | Explicit pass      | `H2hContext` argument to `Callable`               |
| Script engine | `ScriptContext`    | Read-only context bindings                        |

### 8.3 Async / Parallel Processing

When splitting bulk payments across threads:

```java
H2hContext parentContext = H2hContextHolder.get();

executor.submit(() -> {
    H2hContext childContext = H2hContextBuilder.from(parentContext)
        .attribute("paymentIndex", String.valueOf(index))
        .build();
    try {
        H2hContextHolder.set(childContext);
        processPayment(payment);
    } finally {
        H2hContextHolder.clear();
    }
});
```

**Rule:** Never share mutable context across threads. Fork from parent.

***

## 9. MDC Integration

`MdcContextPropagator` maps context fields to SLF4J MDC:

```java
MDC.put("correlationId", context.correlationId());
MDC.put("partnerId", context.partnerId());
MDC.put("countryCode", context.countryCode());
MDC.put("messageType", context.messageType());
MDC.put("batchId", context.batchId());
MDC.put("fileId", context.fileId());
MDC.put("configVersion", context.configVersion());
```

Log pattern (logback):

```xml
<pattern>%d{ISO8601} [%X{correlationId}] [%X{partnerId}] %-5level %logger{36} - %msg%n</pattern>
```

See [Monitoring and Logging](/docs/17-monitoring-and-logging.md).

***

## 10. Script Engine Integration

Scripts receive read-only context bindings:

```java
public record ScriptContext(
    Object body,
    Map<String, Object> headers,
    H2hContext h2hContext,       // read-only
    Map<String, String> customAttrs
) {}
```

Groovy example inside `SCRIPT_EXECUTE` step:

```groovy
def limit = h2hContext.profile().validationRuleset.dailyLimit
if (body.amount > limit) {
    exchange.setProperty('h2h.status', 'MANUAL_REVIEW')
}
```

Scripts **cannot** modify `H2hContext` directly — set exchange properties instead; `ContextProcessor` picks them up.

***

## 11. Job Executor Integration

Broker-delayed jobs (`h2h.jobs.execute` consumer) create a fresh context per execution:

```java
H2hContext jobContext = H2hContextBuilder.create()
    .correlationId(UUID.randomUUID().toString())
    .partnerId(job.getScopeId())
    .countryCode(job.getCountryCode())
    .environment(environment)
    .attribute("jobId", job.getJobId())
    .attribute("jobCode", job.getJobCode())
    .build();
```

***

## 12. Admin API / Partner Portal

Partner status API queries by `correlationId` or `batchId` from context fields stored in transaction metadata.

```
GET /api/v1/transactions?correlationId=a1b2c3d4-...
GET /api/v1/transactions?batchId=BATCH-20260629-001
```

***

## 13. Context in Audit and Metrics

All audit events and metrics tags are derived from context:

```java
auditEventPublisher.publish(AuditEvent.builder()
    .correlationId(context.correlationId())
    .partnerId(context.partnerId())
    .eventType("PAYMENT_POSTED")
    .metadata(Map.of("configVersion", context.configVersion()))
    .build());

metricsRecorder.incrementCounter("h2h_payments_processed_total", Map.of(
    "partner", context.partnerId(),
    "country", context.countryCode(),
    "status", context.status()
));
```

***

## 14. Custom Attributes in Context

Partner custom attributes (EAV) are loaded once at config resolution and attached:

```java
H2hContext context = H2hContextBuilder.create()
    ...
    .attribute("custom.NG_CBN_REF", customAttributeService.get(partnerId, "NG_CBN_REF"))
    .build();
```

Accessible in scripts as `h2hContext.attributes().get("custom.NG_CBN_REF")`.

***

## 15. Module Dependencies

```
h2h-context
├── h2h-config-api      (IntegrationProfile DTO)
└── h2h-common          (shared types)

Consumers:
├── h2h-camel-core
├── h2h-observability
├── h2h-script-engine
├── h2h-job-scheduler
├── h2h-file-management
└── h2h-*-routes
```

***

## 16. Testing

```java
@Test
void shouldPropagateContextThroughPipeline() {
    H2hContext context = H2hContextBuilder.create()
        .correlationId("test-123")
        .partnerId("ACME_NG")
        .build();

    Exchange exchange = new DefaultExchange(camelContext);
    contextPropagator.toExchange(exchange, context);

    assertThat(exchange.getProperty("h2h.correlationId")).isEqualTo("test-123");
}
```

***

## 17. Related Documents

* [Universal Library Extensibility](/docs/20-universal-library-extensibility.md) — `CustomizationProfile` in context
* [Camel Integration Patterns](/docs/08-camel-integration-patterns.md) — exchange property conventions
* [Monitoring and Logging](/docs/17-monitoring-and-logging.md) — MDC and tracing
* [Database-Driven Configuration](/docs/04-database-driven-configuration.md) — profile in context
* [Extensibility Framework](/docs/14-extensibility-framework.md) — script context bindings
* [Design Patterns](/docs/13-design-patterns.md) — Correlation Identifier EIP


---

# 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/18-execution-context.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.
