This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new a842fd64d892 CAMEL-23550: Fix bean lookup in route templates to check
local repository (#23312)
a842fd64d892 is described below
commit a842fd64d8925ad9b26f716dc96d9d9f458ee080
Author: Tom Cunningham <[email protected]>
AuthorDate: Tue May 19 14:56:15 2026 -0400
CAMEL-23550: Fix bean lookup in route templates to check local repository
(#23312)
* CAMEL-23550: Fix bean lookup in route templates to check local repository
first
Kamelets defining beans via the beans: section store them in a local bean
repository
scoped to the RouteTemplateContext. The reifier now checks this local
repository before
falling back to the global registry, allowing route templates to reference
their own beans.
Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
* CAMEL-23550 Add test cases for local-only bean lookup and local/global
bean conflict
---------
Co-authored-by: Claude Sonnet 4.5 <[email protected]>
---
.../org/apache/camel/reifier/AbstractReifier.java | 16 +++++
.../camel/builder/RouteTemplateLocalBeanTest.java | 74 ++++++++++++++++++++++
2 files changed, 90 insertions(+)
diff --git
a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/AbstractReifier.java
b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/AbstractReifier.java
index 2a6d196213d9..f7e32a4740ea 100644
---
a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/AbstractReifier.java
+++
b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/AbstractReifier.java
@@ -25,11 +25,14 @@ import java.util.Set;
import org.apache.camel.CamelContext;
import org.apache.camel.Endpoint;
import org.apache.camel.Expression;
+import org.apache.camel.NamedNode;
import org.apache.camel.NoSuchBeanException;
import org.apache.camel.NoSuchEndpointException;
import org.apache.camel.Predicate;
import org.apache.camel.Route;
+import org.apache.camel.RouteTemplateContext;
import org.apache.camel.model.ExpressionSubElementDefinition;
+import org.apache.camel.model.RouteDefinition;
import org.apache.camel.model.language.ExpressionDefinition;
import org.apache.camel.reifier.language.ExpressionReifier;
import org.apache.camel.spi.BeanRepository;
@@ -208,6 +211,19 @@ public abstract class AbstractReifier implements
BeanRepository {
if (EndpointHelper.isReferenceParameter(name)) {
answer = EndpointHelper.resolveReferenceParameter(camelContext,
name, type, false);
}
+ if (answer == null && route != null) {
+ // check local bean repository from route template context first
+ NamedNode routeNode = route.getRoute();
+ if (routeNode instanceof RouteDefinition routeDef) {
+ RouteTemplateContext rtc = routeDef.getRouteTemplateContext();
+ if (rtc != null) {
+ BeanRepository localRepo = rtc.getLocalBeanRepository();
+ if (localRepo != null) {
+ answer = localRepo.lookupByNameAndType(name, type);
+ }
+ }
+ }
+ }
if (answer == null) {
// fallback to use registry which allows tooling to influence
reifier that uses beans or classes
answer = getRegistry().lookupByNameAndType(name, type);
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 114a311d1f57..f4dd6e8f6838 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
@@ -69,6 +69,80 @@ public class RouteTemplateLocalBeanTest extends
ContextTestSupport {
context.stop();
}
+ @Test
+ public void testLocalBeanFoundByReifier() throws Exception {
+ // Test that AbstractReifier can find a local bean (kamelet scenario)
+ // Local bean is defined via templateBean, NOT in global registry
+ context.addRoutes(new RouteBuilder() {
+ @Override
+ public void configure() {
+
routeTemplate("myTemplate").templateParameter("foo").templateParameter("bar")
+ .templateBean("myLocalBean",
+ (Processor) ex ->
ex.getMessage().setBody("LocalOnly " + ex.getMessage().getBody()))
+ .from("direct:{{foo}}")
+ .to("bean:{{bar}}");
+ }
+ });
+
+ context.start();
+
+ TemplatedRouteBuilder.builder(context, "myTemplate")
+ .parameter("foo", "one")
+ .parameter("bar", "myLocalBean")
+ .routeId("myRoute")
+ .add();
+
+ assertEquals(1, context.getRoutes().size());
+
+ // AbstractReifier should find the local bean and use it
+ Object out = template.requestBody("direct:one", "World");
+ assertEquals("LocalOnly World", out);
+
+ // Bean should NOT be in global registry (kamelet local beans are
scoped to route template)
+ assertNull(context.getRegistry().lookupByName("myLocalBean"));
+
+ context.stop();
+ }
+
+ @Test
+ public void testLocalBeanOverridesGlobalBean() throws Exception {
+ // Test that local bean takes precedence when both local and global
beans exist with same name
+ // This ensures AbstractReifier checks local repository BEFORE global
registry
+
+ // Register a global bean with the same name
+ context.getRegistry().bind("myBar", (Processor) ex ->
ex.getMessage().setBody("Global " + ex.getMessage().getBody()));
+
+ context.addRoutes(new RouteBuilder() {
+ @Override
+ public void configure() {
+
routeTemplate("myTemplate").templateParameter("foo").templateParameter("bar")
+ .from("direct:{{foo}}")
+ .to("bean:{{bar}}");
+ }
+ });
+
+ context.start();
+
+ // Create route with local bean that has the same name as global bean
+ TemplatedRouteBuilder.builder(context, "myTemplate")
+ .parameter("foo", "one")
+ .parameter("bar", "myBar")
+ .bean("myBar", (Processor) ex ->
ex.getMessage().setBody("Local " + ex.getMessage().getBody()))
+ .routeId("myRoute")
+ .add();
+
+ assertEquals(1, context.getRoutes().size());
+
+ // The local bean should take precedence over the global bean
+ Object out = template.requestBody("direct:one", "World");
+ assertEquals("Local World", out);
+
+ // Global bean should still exist in registry
+ assertNotNull(context.getRegistry().lookupByName("myBar"));
+
+ context.stop();
+ }
+
@Test
public void testLocalBeanInBuilder() throws Exception {
context.addRoutes(new RouteBuilder() {