Skip to content
Art2link ESB v2.02 LTS HomeDocumentationBlogContact
Patterns/Routing/Multi-type splitter

Multi-type splitter

One arrival, many messages — and many kinds. A batch holds records of several different sorts; instead of producing N copies of one canonical type the way a splitter does, this variant gives each item its own Message Type as it leaves the pipeline, so orders, invoices and shipments part ways the moment they hit the bus.

A plain splitter debatches an envelope into individual messages that are all the same type. But some feeds are mixed: a single payload carries records of genuinely different kinds, each destined for its own processing. The multi-type splitter handles that case — the debatch and the typing happen together, in the receive pipeline.

The work lives in a custom pipeline component. It walks the envelope, and for each element it decides what kind of record this is and publishes it tagged with the matching Message Type — one item becomes an Order, the next an Invoice, the next a Shipment. The classification is component logic, not a map and not a subscription: the bus only ever sees the already-typed messages that come out the other side.

mixed batch order invoice shipment Multi-type splitter classify + tag per item receive pipeline component Order Invoice Shipment MT MT MT BUS

Take a single inbound payload — a JSON batch whose items each carry a kind — landing on one receive port:

JSONone envelope, mixed records
{ "batch": [
  { "kind": "order",    "po": "A-1001", ... },
  { "kind": "invoice",  "inv": "I-5500", ... },
  { "kind": "shipment", "asn": "S-9120", ... }
] }

The component reads each element, maps its kind to a Message Type, and emits that element as its own message of that type. From there nothing is special: each typed message is a first-class citizen on the bus, so ordinary filtered subscriptions pick them up — one send port per type, each subscribing on the type it cares about:

EXPRESSIONorder send port — subscription
{{Message.MessageType}} == "Order"
EXPRESSIONinvoice send port — subscription
{{Message.MessageType}} == "Invoice"
EXPRESSIONshipment send port — subscription
{{Message.MessageType}} == "Shipment"

This is the natural front half of a content-based router: the router branches one type by a value it carries, whereas the multi-type splitter produces the types themselves, so the branching downstream is just one subscription per type. It is also the mirror image of the normalizer — the normalizer folds many inbound formats into one type, while the multi-type splitter fans one envelope out into many. And as with the plain splitter, the payoff is isolation: a malformed invoice is dead-lettered on its own while the order and shipment beside it sail through.

Every emitted type needs a home. Each Message Type the component can produce should have its schema and at least one subscriber; wire an item the component can’t classify to a dead-letter channel so an unknown kind surfaces instead of vanishing. And carry the source envelope id onto each item’s variables, so you can trace a message back to the batch it came from or re-aggregate later.