{"id":2086,"date":"2026-02-01T01:10:58","date_gmt":"2026-01-31T12:10:58","guid":{"rendered":"https:\/\/www.ronella.xyz\/?p=2086"},"modified":"2026-02-01T01:10:58","modified_gmt":"2026-01-31T12:10:58","slug":"dead-letter-channel-in-apache-camel-with-log-endpoint","status":"publish","type":"post","link":"https:\/\/www.ronella.xyz\/?p=2086","title":{"rendered":"Dead Letter Channel in Apache Camel with Log Endpoint"},"content":{"rendered":"<p>Apache Camel's Dead Letter Channel (DLC) is an Enterprise Integration Pattern that gracefully handles failed messages by routing them to a designated endpoint, preventing route blockages. This article explores DLC configuration using a lightweight log endpoint\u2014no JMS broker required\u2014ideal for development, testing, or simple logging setups. You'll get a complete, runnable example to see it in action.<\/p>\n<h2>What is Dead Letter Channel?<\/h2>\n<p>The DLC activates when a message processing fails after exhausting retries. Unlike Camel's default error handler, which logs exceptions, DLC preserves the original input message and forwards it to a &quot;dead letter&quot; endpoint like a log, file, or queue. Key benefits include message isolation for later analysis and non-blocking route behavior.<\/p>\n<p>It supports redelivery policies for automatic retries before final routing. This pattern shines in enterprise integration where failures (e.g., network issues, data validation errors) must not halt overall flow.<\/p>\n<h2>Why Use Log Endpoint?<\/h2>\n<p>The <code>log<\/code> component offers zero-setup error handling: it captures failures at ERROR level with full exchange details (body, headers, exception stack trace). Perfect for:<\/p>\n<ul>\n<li>Quick debugging without external dependencies.<\/li>\n<li>Console output in standalone apps or containers.<\/li>\n<li>Custom formatting via options like <code>showAll=true<\/code> or <code>multiline=true<\/code>.<\/li>\n<\/ul>\n<p>No database, file system, or broker needed\u2014run it anywhere Camel supports logging (SLF4J\/Logback by default).<\/p>\n<h2>Complete Working Example<\/h2>\n<p>This standalone Java app uses Camel Main to simulate failures via a timer-triggered route. It retries twice, then logs the failure.<\/p>\n<h2>Java DSL Code<\/h2>\n<pre><code class=\"language-java\">import org.apache.camel.builder.RouteBuilder;\nimport org.apache.camel.main.Main;\n\npublic class DeadLetterLogDemo extends RouteBuilder {\n    @Override\n    public void configure() {\n        \/\/ Configure DLC with log endpoint\n        errorHandler(deadLetterChannel(&quot;log:dead?level=ERROR&amp;showAll=true&amp;multiline=true&quot;)\n            .useOriginalMessage()  \/\/ Preserves original input\n            .maximumRedeliveries(2)\n            .redeliveryDelay(1000)\n            .retryAttemptedLogLevel(org.apache.camel.LoggingLevel.WARN));\n\n        \/\/ Route that simulates failure\n        from(&quot;timer:fail?period=5000&amp;repeatCount=1&quot;)\n            .log(&quot;\ud83d\udd25 Starting processing: ${body}&quot;)\n            .process(exchange -&gt; {\n                \/\/ Simulate a runtime failure (e.g., bad data parsing)\n                throw new RuntimeException(&quot;\ud83d\udca5 Simulated processing error!&quot;);\n            })\n            .log(&quot;\u2705 Success log (won&#039;t reach here)&quot;);\n    }\n\n    public static void main(String[] args) throws Exception {\n        Main main = new Main();\n        main.configure().addRoutesBuilder(new DeadLetterLogDemo());\n        main.run(args);  \/\/ Runs until Ctrl+C\n    }\n}<\/code><\/pre>\n<h2>Expected Console Output<\/h2>\n<pre><code>\ud83d\udd25 Starting processing:\nFailed delivery for (MessageId: 25B7DFF9FB26DD8-0000000000000000 on ExchangeId: 25B7DFF9FB26DD8-0000000000000000). On delivery attempt: 0 caught: java.lang.RuntimeException: \ud83d\udca5 Simulated processing error!\nFailed delivery for (MessageId: 25B7DFF9FB26DD8-0000000000000000 on ExchangeId: 25B7DFF9FB26DD8-0000000000000000). On delivery attempt: 1 caught: java.lang.RuntimeException: \ud83d\udca5 Simulated processing error!\nFailed delivery for (MessageId: 25B7DFF9FB26DD8-0000000000000000 on ExchangeId: 25B7DFF9FB26DD8-0000000000000000). On delivery attempt: 2 caught: java.lang.RuntimeException: \ud83d\udca5 Simulated processing error!\nExchange[\n  Id: 25B7DFF9FB26DD8-0000000000000000\n  RouteGroup: null\n  RouteId: route1\n  ExchangePattern: InOnly\n  Properties: {CamelExceptionCaught=java.lang.RuntimeException: \ud83d\udca5 Simulated processing error!, CamelFailureRouteId=route1, CamelFatalFallbackErrorHandler=[route1], CamelToEndpoint=log:\/\/dead?level=ERROR&amp;multiline=true&amp;showAll=true}<\/code><\/pre>\n<h2>Advanced Customizations<\/h2>\n<p>Enhance with processors for richer logging:<\/p>\n<pre><code class=\"language-java\">errorHandler(deadLetterChannel(&quot;log:dead?level=ERROR&quot;)\n    .onExceptionOccurred(exchange -&gt; {\n        exchange.getIn().setHeader(&quot;failureTime&quot;, System.currentTimeMillis());\n        exchange.getIn().setHeader(&quot;errorDetails&quot;, exchange.getException().getMessage());\n    }));<\/code><\/pre>\n<h2>Best Practices<\/h2>\n<ul>\n<li>Always pair with <code>useOriginalMessage()<\/code> to avoid losing input data.<\/li>\n<li>Set <code>maximumRedeliveries=0<\/code> for immediate DLC without retries in tests.<\/li>\n<li>Monitor log volume in production; consider rotating to file or alerting.<\/li>\n<li>Test edge cases: network timeouts, serialization errors, poison messages.<\/li>\n<li>Global DLC via <code>camelContext.setErrorHandlerFactory()<\/code> for app-wide coverage.<\/li>\n<\/ul>\n<p>This setup provides robust, observable error handling. Experiment by changing the failure to a real processor (e.g., invalid JSON parsing) for your use cases.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Apache Camel&#8217;s Dead Letter Channel (DLC) is an Enterprise Integration Pattern that gracefully handles failed messages by routing them to a designated endpoint, preventing route blockages. This article explores DLC configuration using a lightweight log endpoint\u2014no JMS broker required\u2014ideal for development, testing, or simple logging setups. You&#8217;ll get a complete, runnable example to see it [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[92],"tags":[],"_links":{"self":[{"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/posts\/2086"}],"collection":[{"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2086"}],"version-history":[{"count":1,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/posts\/2086\/revisions"}],"predecessor-version":[{"id":2087,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/posts\/2086\/revisions\/2087"}],"wp:attachment":[{"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2086"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2086"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2086"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}