This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch CAMEL-23652-route-template-bean-clash in repository https://gitbox.apache.org/repos/asf/camel.git
commit 34029d8ce1296f0f381f0d5f4a47c4e5d50d470e Author: Claus Ibsen <[email protected]> AuthorDate: Tue Jun 2 20:37:41 2026 +0200 CAMEL-23652: Fix route template local bean not found when param value matches bean name When a template parameter value coincidentally matches a local bean name (e.g., scheme=counter where counter is also a bean), the bean uniqueness logic removed the bean from the registry but failed to add the bean name as a template parameter, making {{beanName}} references unresolvable. Co-Authored-By: Claude Opus 4.6 <[email protected]> --- .../org/apache/camel/impl/DefaultCamelContext.java | 10 +++++++ .../camel/builder/RouteTemplateLocalBeanTest.java | 32 ++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultCamelContext.java b/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultCamelContext.java index c42c04fd7e15..e4732f66ad32 100644 --- a/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultCamelContext.java +++ b/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultCamelContext.java @@ -690,6 +690,7 @@ public class DefaultCamelContext extends SimpleCamelContext implements ModelCame // no side-effect from previously used values that Camel may use in its endpoint // registry and elsewhere if (bbr != null && !bbr.isEmpty()) { + Map<String, String> beanNameMappings = new HashMap<>(); for (Map.Entry<String, Object> param : params.entrySet()) { Object value = param.getValue(); if (value instanceof String oldKey) { @@ -701,9 +702,18 @@ public class DefaultCamelContext extends SimpleCamelContext implements ModelCame routeDefinition.getId(), oldKey, newKey); bbrCopy.put(newKey, bbr.remove(oldKey)); param.setValue(newKey); + beanNameMappings.put(oldKey, newKey); } } } + // ensure bean names removed during clash detection are still + // available as template parameters so they can be referenced + // directly in routes via {{beanName}} + for (Map.Entry<String, String> mapping : beanNameMappings.entrySet()) { + if (!params.containsKey(mapping.getKey())) { + params.put(mapping.getKey(), mapping.getValue()); + } + } // the remainder of the local beans must also have their ids made global unique for (Map.Entry<String, Map<Class<?>, Object>> entry : bbr.entrySet()) { String oldKey = entry.getKey(); diff --git a/core/camel-core/src/test/java/org/apache/camel/builder/RouteTemplateLocalBeanTest.java b/core/camel-core/src/test/java/org/apache/camel/builder/RouteTemplateLocalBeanTest.java index f4dd6e8f6838..bbe7097c2c0a 100644 --- a/core/camel-core/src/test/java/org/apache/camel/builder/RouteTemplateLocalBeanTest.java +++ b/core/camel-core/src/test/java/org/apache/camel/builder/RouteTemplateLocalBeanTest.java @@ -949,4 +949,36 @@ public class RouteTemplateLocalBeanTest extends ContextTestSupport { return answer; } + @Test + public void testLocalBeanWithParamValueClash() throws Exception { + context.addRoutes(new RouteBuilder() { + @Override + public void configure() { + routeTemplate("myTemplate") + .templateParameter("foo") + .templateParameter("scheme") + .templateBean("counter").typeClass(AtomicInteger.class).end() + .from("direct:{{foo}}") + .to("bean:{{counter}}?method=getAndIncrement"); + } + }); + + context.start(); + + TemplatedRouteBuilder.builder(context, "myTemplate") + .parameter("foo", "one") + .parameter("scheme", "counter") + .routeId("myRoute") + .add(); + + assertEquals(1, context.getRoutes().size()); + + Object out = template.requestBody("direct:one", "World"); + assertEquals(0, out); + out = template.requestBody("direct:one", "World"); + assertEquals(1, out); + + context.stop(); + } + }
