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 7fe950d  Kamelet local bean - Created local bean should memorize so 
when using the bean multiple times its the same local bean
7fe950d is described below

commit 7fe950d4d257e38abdae63c096e9003e2cedc229
Author: Claus Ibsen <[email protected]>
AuthorDate: Fri May 14 08:45:48 2021 +0200

    Kamelet local bean - Created local bean should memorize so when using the 
bean multiple times its the same local bean
---
 .../java/org/apache/camel/impl/DefaultModel.java   | 19 ++++++---
 .../camel/builder/RouteTemplateLocalBeanTest.java  | 46 ++++++++++++++++++++++
 2 files changed, 59 insertions(+), 6 deletions(-)

diff --git 
a/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultModel.java 
b/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultModel.java
index 56196e7..b311748 100644
--- 
a/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultModel.java
+++ 
b/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultModel.java
@@ -66,6 +66,7 @@ import org.apache.camel.support.ScriptHelper;
 import org.apache.camel.support.service.ServiceHelper;
 import org.apache.camel.util.AntPathMatcher;
 import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.function.Suppliers;
 
 public class DefaultModel implements Model {
 
@@ -366,7 +367,9 @@ public class DefaultModel implements Model {
                 final ScriptingLanguage slan = lan instanceof 
ScriptingLanguage ? (ScriptingLanguage) lan : null;
                 if (slan != null) {
                     // scripting language should be evaluated with route 
template context as binding
-                    routeTemplateContext.bind(b.getName(), clazz, () -> {
+                    // and memorize so the script is only evaluated once and 
the local bean is the same
+                    // if a route template refers to the local bean multiple 
times
+                    routeTemplateContext.bind(b.getName(), clazz, 
Suppliers.memorize(() -> {
                         Map<String, Object> bindings = new HashMap<>();
                         // use rtx as the short-hand name, as context would 
imply its CamelContext
                         bindings.put("rtc", routeTemplateContext);
@@ -375,10 +378,12 @@ public class DefaultModel implements Model {
                             setPropertiesOnTarget(camelContext, local, props);
                         }
                         return local;
-                    });
+                    }));
                 } else {
                     // exchange based languages needs a dummy exchange to be 
evaluated
-                    routeTemplateContext.bind(b.getName(), clazz, () -> {
+                    // and memorize so the script is only evaluated once and 
the local bean is the same
+                    // if a route template refers to the local bean multiple 
times
+                    routeTemplateContext.bind(b.getName(), clazz, 
Suppliers.memorize(() -> {
                         ExchangeFactory ef = 
camelContext.adapt(ExtendedCamelContext.class).getExchangeFactory();
                         Exchange dummy = ef.create(false);
                         try {
@@ -396,20 +401,22 @@ public class DefaultModel implements Model {
                         } finally {
                             ef.release(dummy);
                         }
-                    });
+                    }));
                 }
             } else if (b.getBeanClass() != null || b.getType() != null && 
b.getType().startsWith("#class:")) {
                 Class<?> clazz = b.getBeanClass() != null
                         ? b.getBeanClass() : 
camelContext.getClassResolver().resolveMandatoryClass(b.getType().substring(7));
                 // we only have the bean class so we use that to create a new 
bean via the injector
+                // and memorize so the bean is only created once and the local 
bean is the same
+                // if a route template refers to the local bean multiple times
                 routeTemplateContext.bind(b.getName(), clazz,
-                        () -> {
+                        Suppliers.memorize(() -> {
                             Object local = 
camelContext.getInjector().newInstance(clazz);
                             if (!props.isEmpty()) {
                                 setPropertiesOnTarget(camelContext, local, 
props);
                             }
                             return local;
-                        });
+                        }));
             } else if (b.getType() != null && 
b.getType().startsWith("#type:")) {
                 Class<?> clazz = 
camelContext.getClassResolver().resolveMandatoryClass(b.getType().substring(6));
                 Set<?> found = 
getCamelContext().getRegistry().findByType(clazz);
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 83337fb0..7228b50 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
@@ -23,6 +23,7 @@ import org.apache.camel.ContextTestSupport;
 import org.apache.camel.Exchange;
 import org.apache.camel.Processor;
 import org.apache.camel.RouteTemplateContext;
+import org.apache.camel.component.mock.MockEndpoint;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -650,6 +651,47 @@ public class RouteTemplateLocalBeanTest extends 
ContextTestSupport {
         context.stop();
     }
 
+    @Test
+    public void testLocalBeanMemorize() throws Exception {
+        context.addRoutes(new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                
routeTemplate("myTemplate").templateParameter("foo").templateParameter("bar").templateParameter("hi")
+                        .templateBean("myBar").property("prefix", 
"{{hi}}").typeClass(BuilderThreeProcessor.class).end()
+                        .from("direct:{{foo}}")
+                        // use unique endpoints to force referring the to bean 
twice
+                        .to("bean:{{bar}}")
+                        .to("bean:{{bar}}?method=process")
+                        .to("mock:result");
+            }
+        });
+
+        context.start();
+
+        TemplatedRouteBuilder.builder(context, "myTemplate")
+                .parameter("foo", "one")
+                .parameter("bar", "myBar")
+                .parameter("hi", "Davs")
+                .routeId("myRoute")
+                .add();
+
+        assertEquals(1, context.getRoutes().size());
+
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.expectedBodiesReceived("DavsBuilder3 DavsBuilder3 World");
+        mock.expectedHeaderReceived("counter", 2);
+
+        Object out = template.requestBody("direct:one", "World");
+        assertEquals("DavsBuilder3 DavsBuilder3 World", out);
+
+        assertMockEndpointsSatisfied();
+
+        // should not be a global bean
+        assertNull(context.getRegistry().lookupByName("myBar"));
+
+        context.stop();
+    }
+
     public static class BuilderTwoProcessor implements Processor {
 
         private String prefix = "";
@@ -670,6 +712,7 @@ public class RouteTemplateLocalBeanTest extends 
ContextTestSupport {
     public static class BuilderThreeProcessor implements Processor {
 
         private String prefix = "";
+        private int counter;
 
         public String getPrefix() {
             return prefix;
@@ -681,8 +724,11 @@ public class RouteTemplateLocalBeanTest extends 
ContextTestSupport {
 
         @Override
         public void process(Exchange exchange) throws Exception {
+            counter++;
             exchange.getMessage().setBody(prefix + "Builder3 " + 
exchange.getMessage().getBody());
+            exchange.getMessage().setHeader("counter", counter);
         }
+
     }
 
     public Processor createBuilderProcessor() {

Reply via email to