Splitter
Break a composite message into multiple atomic messages. An EDIFACT INVOIC carrying 100 invoices becomes 100 independent messages. A multi-delivery X12 856 becomes one message per delivery. The pattern that turns a batch into a stream.
Problem
In EDI, partners often group several business units in a single interchange: 100 invoices in one INVOIC, 50 ship lines in a multi-delivery DESADV, 20 purchase orders in a batched 850. This densification suits the sender (fewer files, fewer transmissions), but complicates the receiver who wants to handle each unit independently: idempotency per invoice, retry per line, status per order.
Forces
- Granularity of reprocessing. If one invoice out of 100 is in error, we want to isolate that one and replay the other 99 — not replay everything.
- Parallelisation. Multiple consumers can process children in parallel, reducing total throughput time.
- Business atomicity. A retry unit should match a business unit — not a transport batch.
- Traceability. Children must carry a reference to the parent so operators can reconstruct lineage on incident.
Solution
Hohpe & Woolf (EIP §259, under Splitter, sometimes Sequencer) prescribe a component that: (a) receives the composite message, (b) iterates over sub-elements per the format grammar, (c) emits one message per sub-element propagating the necessary headers (sender, receiver, parent correlation), (d) optionally signals end of sequence with a last marker.
┌────────────────────┐
INVOIC (100 inv) │ Splitter │
────────▶│ (iterate over UNH │
│ or LIN groups) │
└─────────┬──────────┘
│
┌─────────────┼─────────────┐
│ │ │
▼ ▼ ▼
invoice 1 invoice 2 invoice 100
(UNH=INVOIC) (UNH=INVOIC) (UNH=INVOIC) Topology
Three variants:
- Eager Splitter. Loads the entire composite in memory, emits each child. Simple, but fails on very large files (a 500 MB DESADV).
- Streaming Splitter. Parses on the fly, emits children while reading. Indispensable above a few tens of MB.
- Splitter + Aggregator. A common pair in production — split for parallelism, then aggregate the results before responding to the original sender.
EDI implementation
Two levels of splitting:
- Interchange level — one UNH per child. An EDIFACT
interchange can contain several
UNHblocks (up to aUNZ). The splitter emits one message perUNH ... UNTblock. The most natural and most common split. - Message level —
LINlines in EDIFACT,HLin X12. Rarer, but useful when a single message contains multiple distinct business units. Classic case: an INVOIC where eachLINis a separate invoice (debatable contractually but observed).
UNB+UNOC:3+SENDER:14+RECEIVER:14+260514:1545+BATCH001'
UNH+1+INVOIC:D:96A:UN:EAN008'
BGM+380+INV-001+9'
...
UNT+42+1'
UNH+2+INVOIC:D:96A:UN:EAN008'
BGM+380+INV-002+9'
...
UNT+38+2'
UNH+3+INVOIC:D:96A:UN:EAN008'
BGM+380+INV-003+9'
...
UNT+45+3'
UNZ+3+BATCH001'
The splitter on this batch emits three messages: each one composed
of a new UNB (regenerated or inherited), the UNH to UNT block of the invoice, and a new UNZ. UNB sender
and receiver are propagated as-is. The UNB Interchange
Control Reference can be (a) regenerated (one per child) or
(b) suffixed (BATCH001-001, BATCH001-002) per the local convention. Option (b) is
preferable because it preserves explicit parent traceability.
Parent / child tracing
Each child must carry a reference to the parent in its integration context (not necessarily in the EDIFACT payload, which does not always support it, but in the send metadata). Three pieces of information are essential:
-
parent.interchange_id— the original composite's UNB CTRL. -
parent.position— the index of the child in the composite (1, 2, 3...). -
parent.total— the sequence size (useful for any downstream aggregator).
Anti-patterns
- Eager splitter on large file. Loading 500 MB into memory to split causes heap pressure, triggers GC and ends in OOM. Always stream.
- Loss of parent. Without explicit parent correlation, the batch window cannot be reconstructed on incident. The audit log must always show lineage.
- Splitter without downstream dedup. If the splitter re-emits the same child after a crash, an Idempotent Receiver must follow, otherwise the child is integrated twice.
- Implicit position by arrival order. If the position is not stored explicitly, we depend on queue order — which is not guaranteed in most modern brokers.
Related patterns
- Aggregator — the inverse pattern, often paired downstream.
- Message Router — applied on each child after split.
- Idempotency — each child must have its own uniqueness key.
Sources
- Hohpe G., Woolf B. — Enterprise Integration Patterns, Splitter (§259) and Sequencer. enterpriseintegrationpatterns.com — Splitter
- Apache Camel — Split EIP, streaming and tokenizer support. camel.apache.org — Split EIP
- UN/EDIFACT — ISO 9735 §6.3. Specification of
UNH/UNTbracketing that defines the natural granularity of splitting. - ASC X12 — 004010 §B.1.1.3.4. Specification of
ST/SEbracketing for X12 splitting.