ediverse Explore the platform

Spotlight PEPPOL BIS Billing 3.0 The EU e-invoicing mandate is here — France Sept 2026, Belgium Jan 2026, Germany 2025.

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.

plaintext topology.txt
┌────────────────────┐
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 UNH blocks (up to a UNZ). The splitter emits one message per UNH ... UNT block. The most natural and most common split.
  • Message level — LIN lines in EDIFACT, HL in X12. Rarer, but useful when a single message contains multiple distinct business units. Classic case: an INVOIC where each LIN is a separate invoice (debatable contractually but observed).
edifact invoic-batch-3.edi
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.
  • 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 CamelSplit EIP, streaming and tokenizer support. camel.apache.org — Split EIP
  • UN/EDIFACT — ISO 9735 §6.3. Specification of UNH/UNT bracketing that defines the natural granularity of splitting.
  • ASC X12 — 004010 §B.1.1.3.4. Specification of ST/SE bracketing for X12 splitting.