Multi-Step Route with Direct: Calls

Overview

Breaks a complex integration into multiple smaller routes connected by direct: calls. Each sub-route has a single responsibility and can be understood and debugged independently.

Route: routes/multi-step-import.xml

XML
<routes xmlns="http://camel.apache.org/schema/spring">

    <!-- Entry point: reads file and delegates to validation -->
    <route id="mainImport">
        <from uri="file:{{import.fromUri}}"/>
        <split>
            <tokenize group="5000" token="
"/>
            <to uri="pfx-csv:unmarshal?skipHeaderRecord=true&amp;delimiter=,"/>
            <to uri="direct:validateRows"/>
        </split>
    </route>

    <!-- Validates rows: skips batches where any row has an empty SKU -->
    <route id="validateRows">
        <from uri="direct:validateRows"/>
        <filter>
            <groovy>body.every { row -> row.sku != null &amp;&amp; !row.sku.isEmpty() }</groovy>
        </filter>
        <to uri="direct:loadRows"/>
    </route>

    <!-- Loads rows into Pricefx -->
    <route id="loadRows">
        <from uri="direct:loadRows"/>
        <to uri="pfx-api:loaddata?objectType=P&amp;mapper=productMapper"/>
    </route>

</routes>

When to Use direct: vs seda:


direct:

seda:

Execution

Synchronous (same thread)

Asynchronous (new thread)

Error propagation

Errors propagate back to caller

Errors are isolated

Use when

You need the result or want errors to stop the flow

Fire-and-forget, parallel processing

Common Pitfalls

  • direct: routes must be in the same Camel context — they cannot span separate IM instances

  • Circular direct: calls (A calls B calls A) will cause a stack overflow

  • seda: adds concurrency overhead — use it only when async processing is truly needed

  • Each sub-route must have a unique id across the entire project