{"id":2095,"date":"2026-02-02T23:44:40","date_gmt":"2026-02-02T10:44:40","guid":{"rendered":"https:\/\/www.ronella.xyz\/?p=2095"},"modified":"2026-02-02T23:44:40","modified_gmt":"2026-02-02T10:44:40","slug":"apache-camel-route-templates-with-java-dsl","status":"publish","type":"post","link":"https:\/\/www.ronella.xyz\/?p=2095","title":{"rendered":"Apache Camel Route Templates with Java DSL"},"content":{"rendered":"<p>Apache Camel route templates in Java DSL let you define a reusable route \u201cshape\u201d and then create many concrete routes from it by supplying parameters. This avoids copy\u2011pasting similar routes and centralizes changes.<\/p>\n<hr \/>\n<h2>Core idea in Java DSL<\/h2>\n<p>In Java DSL, a route template is declared inside a <code>RouteBuilder<\/code> using <code>routeTemplate(&quot;id&quot;)<\/code> and a set of <code>templateParameter(...)<\/code> entries. Placeholders like <code>{{name}}<\/code> and <code>{{period}}<\/code> inside the route definition are filled in when you create concrete routes from the template.<\/p>\n<p>Conceptually:<br \/>\n$$<br \/>\n\\text{routeTemplate(&quot;id&quot;)} + \\text{parameters} \\Rightarrow \\text{concrete route}<br \/>\n$$<br \/>\nThis separates <em>what changes<\/em> (parameters) from <em>what stays the same<\/em> (the processing steps), so you can add or modify routes by changing parameters instead of duplicating code.<\/p>\n<hr \/>\n<h2>Defining a route template<\/h2>\n<p>You define the template in a <code>RouteBuilder<\/code> just like a normal route, but with <code>routeTemplate<\/code> and <code>templateParameter<\/code>.<\/p>\n<pre><code class=\"language-java\">import org.apache.camel.builder.RouteBuilder;\n\n\/\/ Defines the route template using Java DSL\nstatic class MyRouteTemplates extends RouteBuilder {\n    @Override\n    public void configure() throws Exception {\n        routeTemplate(&quot;greetingTemplate&quot;)\n                .templateParameter(&quot;name&quot;)\n                .templateParameter(&quot;greeting&quot;)\n                .templateParameter(&quot;period&quot;, &quot;3s&quot;)\n\n                .from(&quot;timer:{{name}}?period={{period}}&quot;)\n                .setBody(simple(&quot;{{greeting}} from route {{name}} at ${date:now:HH:mm:ss}&quot;))\n                .log(&quot;${body}&quot;);\n    }\n}<\/code><\/pre>\n<p>Why it\u2019s structured like this:<\/p>\n<ul>\n<li><code>routeTemplate(&quot;greetingTemplate&quot;)<\/code> marks this as a template (a blueprint), not a route that runs by itself.<\/li>\n<li>Each <code>templateParameter(...)<\/code> declares one thing that can vary between route instances and can optionally have a default.<\/li>\n<li><code>{{name}}<\/code>, <code>{{greeting}}<\/code>, and <code>{{period}}<\/code> are placeholders; Camel will substitute them when you create real routes from this template.<\/li>\n<\/ul>\n<p>All variable pieces are explicitly listed as parameters, so the template is easy to understand and validate.<\/p>\n<hr \/>\n<h2>Creating routes from the template with TemplatedRouteBuilder<\/h2>\n<p>To turn the template into real routes, you use <code>TemplatedRouteBuilder<\/code> with the <code>CamelContext<\/code> and supply parameter values.<a href=\"https:\/\/www.javadoc.io\/static\/org.apache.camel\/camel-core-model\/3.20.2\/org\/apache\/camel\/builder\/TemplatedRouteBuilder.html\">javadoc+1<\/a><\/p>\n<pre><code class=\"language-java\">import org.apache.camel.CamelContext;\nimport org.apache.camel.builder.TemplatedRouteBuilder;\nimport org.apache.camel.impl.DefaultCamelContext;\n\nvoid main() throws Exception {\n    CamelContext context = new DefaultCamelContext();\n\n    \/\/ Register template\n    context.addRoutes(new MyRouteTemplates());\n\n    \/\/ Create routes from template using TemplatedRouteBuilder\n    TemplatedRouteBuilder.builder(context, &quot;greetingTemplate&quot;)\n            .routeId(&quot;helloFast&quot;)\n            .parameter(&quot;name&quot;, &quot;fast&quot;)\n            .parameter(&quot;greeting&quot;, &quot;Hello&quot;)\n            .parameter(&quot;period&quot;, &quot;2s&quot;)\n            .add();\n\n    TemplatedRouteBuilder.builder(context, &quot;greetingTemplate&quot;)\n            .routeId(&quot;helloSlow&quot;)\n            .parameter(&quot;name&quot;, &quot;slow&quot;)\n            .parameter(&quot;greeting&quot;, &quot;Kia ora&quot;)\n            .parameter(&quot;period&quot;, &quot;5s&quot;)\n            .add();\n\n    context.start();\n\n    \/\/ Let timers fire for a while\n    Thread.sleep(15000);\n\n    context.stop();\n}<\/code><\/pre>\n<p>What\u2019s happening and why:<\/p>\n<ul>\n<li><code>context.addRoutes(new MyRouteTemplates())<\/code> loads the template into the <code>CamelContext<\/code>, but does not yet create concrete routes.<\/li>\n<li>Each <code>TemplatedRouteBuilder.builder(context, &quot;greetingTemplate&quot;)<\/code> call:\n<ul>\n<li>Selects the template by id (<code>greetingTemplate<\/code>).<\/li>\n<li>Assigns a <code>routeId<\/code> for the route instance.<\/li>\n<li>Supplies parameter values (<code>name<\/code>, <code>greeting<\/code>, <code>period<\/code>).<\/li>\n<li>Calls <code>.add()<\/code> to materialize and register a concrete route.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>You end up with multiple active routes that share the same logic but differ only in their parameters.<\/p>\n<hr \/>\n<h2>Optional and negated parameters<\/h2>\n<p>Special placeholder variants help with optional and Boolean parameters inside templates:<\/p>\n<ul>\n<li><code>{{?param}}<\/code> \u2192 if <code>param<\/code> is set, include its value; if not, drop the option entirely from the URI.<\/li>\n<li><code>{{!param}}<\/code> \u2192 use the opposite Boolean value of <code>param<\/code>.<\/li>\n<\/ul>\n<p>Example with clear naming:<\/p>\n<pre><code class=\"language-java\">routeTemplate(&quot;httpTemplate&quot;)\n    .templateParameter(&quot;path&quot;)\n    .templateParameter(&quot;replyTimeout&quot;)\n    .templateParameter(&quot;disableLogging&quot;)\n\n    .from(&quot;direct:start&quot;)\n    .to(&quot;http:\/\/example.com\/{{path}}&quot;\n        + &quot;?replyTimeout={{?replyTimeout}}&quot;\n        + &quot;&amp;loggingEnabled={{!disableLogging}}&quot;);<\/code><\/pre>\n<p>Behavior and rationale:<\/p>\n<ul>\n<li>If <code>replyTimeout<\/code> is not provided, the <code>replyTimeout<\/code> option is omitted from the URI entirely, so you avoid dangling <code>replyTimeout=<\/code>.<\/li>\n<li>If <code>disableLogging = true<\/code>, then <code>{{!disableLogging}}<\/code> becomes <code>false<\/code>, so <code>loggingEnabled=false<\/code> on the endpoint.<\/li>\n<li>If <code>disableLogging = false<\/code>, then <code>loggingEnabled=true<\/code>.<\/li>\n<\/ul>\n<p>Use <code>{{!param}}<\/code> when the semantics of the parameter are intentionally opposite to the endpoint\u2019s option name (e.g., <code>disableX<\/code> vs <code>enabledX<\/code>); when they are aligned, simply use <code>{{param}}<\/code>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Apache Camel route templates in Java DSL let you define a reusable route \u201cshape\u201d and then create many concrete routes from it by supplying parameters. This avoids copy\u2011pasting similar routes and centralizes changes. Core idea in Java DSL In Java DSL, a route template is declared inside a RouteBuilder using routeTemplate(&quot;id&quot;) and a set of [&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\/2095"}],"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=2095"}],"version-history":[{"count":1,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/posts\/2095\/revisions"}],"predecessor-version":[{"id":2097,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/posts\/2095\/revisions\/2097"}],"wp:attachment":[{"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2095"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2095"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2095"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}