Error Handling in Routes
Overview
Production integrations need proper error handling -- retry logic, success/failure callbacks, and alerting. This example shows how to combine IM's built-in error handler with route-level error handling patterns.
Built-in Error Handler (Properties-Based)
IM provides a default error handler configured via application.properties. This handles retries automatically for known transient errors:
config/application.properties
# Enable the default error handler (enabled by default)
integration.route-error-handling.enabled=true
# Retry configuration
integration.route-error-handling.maximumRedeliveries=10
integration.route-error-handling.redeliveryDelay=2000
integration.route-error-handling.maximumRedeliveryDelay=300000
integration.route-error-handling.useExponentialBackOff=true
integration.route-error-handling.backOffMultiplier=2.0
# Email notifications on final failure
integration.route-error-handling.enable-sending-mail=true
integration.route-error-handling.email.smtpHost={{smtp.host}}
integration.route-error-handling.email.smtPort={{smtp.port}}
integration.route-error-handling.email.mailFrom=integration_{{pfx.partition}}@pricefx.eu
integration.route-error-handling.email.mailTo={{alert.email}};integration@pricefx.eu
integration.route-error-handling.email.mailSubject={{pfx.partition}} - Integration Error
This handles ConnectException, ConnectTimeoutException, RecoverableException, and HTTP 409/503/504 automatically. All other errors fail immediately after exhausting retries.
Route-Level: onCompletion Pattern
Use onCompletion for success/failure callbacks -- logging, notifications, cleanup:
routes/import-with-error-handling.xml
<routes xmlns="http://camel.apache.org/schema/spring">
<route id="import-with-error-handling">
<from uri="file:{{import.products.directory}}?{{archive.file}}&{{read.lock}}"/>
<log message="Starting product import: ${header.CamelFileNameOnly}" loggingLevel="INFO"/>
<to uri="pfx-csv:streamingUnmarshal?skipHeaderRecord=true&useReusableParser=true"/>
<to uri="pfx-api:loaddataFile?objectType=P&mapper=import-products.mapper&batchSize=200000"/>
<log message="Product import completed: ${header.CamelFileNameOnly}" loggingLevel="INFO"/>
<!-- Success callback -->
<onCompletion onCompleteOnly="true">
<log message="SUCCESS: ${header.CamelFileNameOnly} imported successfully" loggingLevel="INFO"/>
</onCompletion>
<!-- Failure callback -->
<onCompletion onFailureOnly="true">
<log message="FAILED: ${header.CamelFileNameOnly} - ${exception.message}" loggingLevel="ERROR"/>
</onCompletion>
</route>
</routes>
Route-Level: doTry/doCatch Pattern
Use doTry/doCatch when you need to handle specific exceptions differently within the route:
routes/import-with-trycatch.xml
<routes xmlns="http://camel.apache.org/schema/spring">
<route id="import-with-trycatch">
<from uri="file:{{import.products.directory}}?{{archive.file}}&{{read.lock}}"/>
<doTry>
<to uri="pfx-csv:streamingUnmarshal?skipHeaderRecord=true&useReusableParser=true"/>
<to uri="pfx-api:loaddataFile?objectType=P&mapper=import-products.mapper&batchSize=200000"/>
<doCatch>
<exception>net.pricefx.integration.api.exception.FormatException</exception>
<log message="Bad CSV format in ${header.CamelFileNameOnly}: ${exception.message}" loggingLevel="ERROR"/>
<!-- File is already archived by the file consumer -- no need to move it -->
</doCatch>
<doCatch>
<exception>net.pricefx.integration.api.exception.NonRecoverableException</exception>
<log message="Configuration error: ${exception.message}" loggingLevel="ERROR"/>
</doCatch>
</doTry>
</route>
</routes>
Combined: DMDS Import with Full Error Handling
A production-ready DMDS import combining onCompletion (for mandatory flush) with proper error logging:
routes/import-datasource-production.xml
<routes xmlns="http://camel.apache.org/schema/spring">
<route id="import-datasource-production">
<from uri="file:{{import.ds.directory}}?{{archive.file}}&{{read.lock}}"/>
<log message="Starting DS import: ${header.CamelFileNameOnly}" loggingLevel="INFO"/>
<split aggregationStrategy="recordsCountAggregation" streaming="true">
<tokenize token="
" group="10000"/>
<to uri="pfx-csv:unmarshal?skipHeaderRecord=true"/>
<to uri="pfx-api:loaddata?objectType=DM&dsUniqueName=Product&mapper=import-datasource-production.mapper"/>
</split>
<log message="DS load complete. Records: ${header.PfxTotalInputRecordsCount}, Failed: ${header.PfxTotalFailedInputRecordsCount}" loggingLevel="INFO"/>
<!-- Flush ONLY on success -- never flush incomplete data -->
<onCompletion onCompleteOnly="true">
<log message="Flushing DMDS.Product" loggingLevel="INFO"/>
<to uri="pfx-api:flush?dataFeedName=DMF.Product&dataSourceName=DMDS.Product"/>
<log message="Flush complete" loggingLevel="INFO"/>
</onCompletion>
<!-- Log failure without flushing -->
<onCompletion onFailureOnly="true">
<log message="FAILED: DS import of ${header.CamelFileNameOnly} - data NOT flushed" loggingLevel="ERROR"/>
</onCompletion>
</route>
</routes>
Decision Guide
|
Pattern |
When to Use |
|---|---|
|
Properties-based error handler |
Always -- provides automatic retry + email for transient errors |
|
|
Post-success actions: flush, notifications, downstream triggers |
|
|
Failure logging, alerting, cleanup |
|
|
Different handling per exception type within the route |
Important: onCompletion runs outside the error handler -- it always executes regardless of retry configuration. doTry/doCatch runs inside the route and catches exceptions before they reach the error handler.
Common Pitfalls
-
onCompletioninside<split>: Will execute after every batch, not once at the end. Always place it directly inside<route>, outside<split>. -
Flushing on failure: Never use
onCompletion(withoutonCompleteOnly) for DMDS flush -- it would flush incomplete data on failure. -
Catching retryable errors in
doCatch: If you catchConnectExceptionindoCatch, the default error handler will NOT retry it. Let the error handler handle transient errors. -
Missing email properties: If
enable-sending-mail=truebut SMTP properties are wrong, the error email itself fails silently. Test email delivery in QA first.
See Also
-
Error Handling Reference -- all properties, retry timeline, email templates
-
Troubleshooting -- common runtime errors and solutions