You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by nf...@apache.org on 2022/11/29 15:13:15 UTC

[camel] branch main updated: CAMEL-18764: camel-core - Add unit test and fix regressions (#8794)

This is an automated email from the ASF dual-hosted git repository.

nfilotto 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 89691a2a857 CAMEL-18764: camel-core - Add unit test and fix regressions (#8794)
89691a2a857 is described below

commit 89691a2a857a14c498767944c651bae022f45a82
Author: Nicolas Filotto <es...@users.noreply.github.com>
AuthorDate: Tue Nov 29 16:13:06 2022 +0100

    CAMEL-18764: camel-core - Add unit test and fix regressions (#8794)
    
    ## Motivation
    
    The first fix allowing to build a templated route from a template defined using a different DSL, makes [several tests fail](https://ci-builds.apache.org/job/Camel/job/Apache%20Camel/job/main/810/testReport/) that should be fixed:
    
    * org.apache.camel.cdi.templatedroute.TemplatedRouteTest.sendMessageToInbound
    * org.apache.camel.component.kamelet.TemplatedRouteKameletTest.testKamelet
    * org.apache.camel.dsl.yaml.TemplatedRouteTest.create templated route
    * org.apache.camel.dsl.yaml.TemplatedRouteTest.create templated-route
    
    ## Modifications:
    
    * Add missing calls to the new method `addTemplatedRoutes` ensuring that it is called once all the route templates are added to the context
    * Provide the Camel context when it is known to `populateTemplatedRoutes` to prevent getting `CamelContext has not been injected`
    * Add a unit test ensuring that the bug is really fixed
    * Rename `CamelTestSupporOneContextForAllTest` to `CamelTestSupportOneContextForAllTest`
     and fix the violations inside (not related to the initial issue)
---
 .../org/apache/camel/cdi/CdiCamelExtension.java    | 38 ++++++++++++--
 .../apache/camel/test/junit5/CamelTestSupport.java |  6 ++-
 ...a => CamelTestSupportOneContextForAllTest.java} | 17 ++----
 .../java/org/apache/camel/spi/RoutesLoader.java    |  3 ++
 .../org/apache/camel/builder/RouteBuilder.java     |  7 ++-
 .../XmlMainTemplatedRouteFromDifferentDSLTest.java | 60 ++++++++++++++++++++++
 .../camel/main/xml/camel-my-route-template.xml     | 29 +++++++++++
 7 files changed, 142 insertions(+), 18 deletions(-)

diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelExtension.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelExtension.java
index 0953d9de5f8..aac4b848071 100644
--- a/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelExtension.java
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelExtension.java
@@ -23,9 +23,11 @@ import java.lang.reflect.Type;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.BooleanSupplier;
 import java.util.function.Function;
 import java.util.stream.Stream;
 
@@ -432,13 +434,17 @@ public class CdiCamelExtension implements Extension {
             Set<Bean<?>> routes = new HashSet<>(manager.getBeans(RoutesBuilder.class, Any.Literal.INSTANCE));
             routes.addAll(manager.getBeans(RouteContainer.class, Any.Literal.INSTANCE));
             for (Bean<?> context : manager.getBeans(CamelContext.class, Any.Literal.INSTANCE)) {
+                List<BooleanSupplier> postAdditionActions = new ArrayList<>();
                 for (Bean<?> route : routes) {
                     Set<Annotation> qualifiers = new HashSet<>(context.getQualifiers());
                     qualifiers.retainAll(route.getQualifiers());
                     if (qualifiers.size() > 1) {
-                        deploymentException |= !addRouteToContext(route, context, manager, adv);
+                        deploymentException |= !addRouteToContext(route, context, manager, adv, postAdditionActions);
                     }
                 }
+                for (BooleanSupplier action : postAdditionActions) {
+                    deploymentException |= !action.getAsBoolean();
+                }
             }
             // Let's return to avoid starting misconfigured contexts
             if (deploymentException) {
@@ -474,14 +480,40 @@ public class CdiCamelExtension implements Extension {
         Stream.of(producerBeans, producerQualifiers).forEach(Map::clear);
     }
 
+    /**
+     * Gives an action that adds the templated routes defined in the given builder to the given context.
+     * 
+     * @return a {@link BooleanSupplier} that gives {@code true} if the addition was successful, {@code false}
+     *         otherwise.
+     */
+    private BooleanSupplier templatedRoutesAddition(
+            Bean<?> routeBean, AfterDeploymentValidation adv, CamelContext context, RoutesBuilder builder) {
+        return () -> {
+            try {
+                context.addTemplatedRoutes(builder);
+                return true;
+            } catch (Exception cause) {
+                adv.addDeploymentProblem(
+                        new InjectionException(
+                                "Error adding templated routes of type [" + routeBean.getBeanClass().getName() + "] "
+                                               + "to Camel context [" + context.getName() + "]",
+                                cause));
+            }
+            return false;
+        };
+    }
+
     private boolean addRouteToContext(
-            Bean<?> routeBean, Bean<?> contextBean, BeanManager manager, AfterDeploymentValidation adv) {
+            Bean<?> routeBean, Bean<?> contextBean, BeanManager manager, AfterDeploymentValidation adv,
+            List<BooleanSupplier> postAdditionActions) {
         try {
             CamelContext context = getReference(manager, CamelContext.class, contextBean);
             try {
                 Object route = getReference(manager, Object.class, routeBean);
                 if (route instanceof RoutesBuilder) {
-                    context.addRoutes((RoutesBuilder) route);
+                    RoutesBuilder builder = (RoutesBuilder) route;
+                    context.addRoutes(builder);
+                    postAdditionActions.add(templatedRoutesAddition(routeBean, adv, context, builder));
                 } else if (route instanceof RouteContainer) {
                     context.getExtension(Model.class).addRouteDefinitions(((RouteContainer) route).getRoutes());
                 } else if (route instanceof RouteTemplateContainer) {
diff --git a/components/camel-test/camel-test-junit5/src/main/java/org/apache/camel/test/junit5/CamelTestSupport.java b/components/camel-test/camel-test-junit5/src/main/java/org/apache/camel/test/junit5/CamelTestSupport.java
index 32f5e7867e8..0650c596755 100644
--- a/components/camel-test/camel-test-junit5/src/main/java/org/apache/camel/test/junit5/CamelTestSupport.java
+++ b/components/camel-test/camel-test-junit5/src/main/java/org/apache/camel/test/junit5/CamelTestSupport.java
@@ -523,9 +523,13 @@ public abstract class CamelTestSupport
                 }
             }
             for (RoutesBuilder builder : builders) {
-                LOG.debug("Using created route builder: {}", builder);
+                LOG.debug("Using created route builder to add routes: {}", builder);
                 context.addRoutes(builder);
             }
+            for (RoutesBuilder builder : builders) {
+                LOG.debug("Using created route builder to add templated routes: {}", builder);
+                context.addTemplatedRoutes(builder);
+            }
             replaceFromEndpoints();
             boolean skip = "true".equalsIgnoreCase(System.getProperty("skipStartingCamelContext"));
             if (skip) {
diff --git a/components/camel-test/camel-test-junit5/src/test/java/org/apache/camel/test/junit5/CamelTestSupporOneContextForAllTest.java b/components/camel-test/camel-test-junit5/src/test/java/org/apache/camel/test/junit5/CamelTestSupportOneContextForAllTest.java
similarity index 86%
rename from components/camel-test/camel-test-junit5/src/test/java/org/apache/camel/test/junit5/CamelTestSupporOneContextForAllTest.java
rename to components/camel-test/camel-test-junit5/src/test/java/org/apache/camel/test/junit5/CamelTestSupportOneContextForAllTest.java
index 3f8c0ffdbe0..58d1340608e 100644
--- a/components/camel-test/camel-test-junit5/src/test/java/org/apache/camel/test/junit5/CamelTestSupporOneContextForAllTest.java
+++ b/components/camel-test/camel-test-junit5/src/test/java/org/apache/camel/test/junit5/CamelTestSupportOneContextForAllTest.java
@@ -27,15 +27,10 @@ import org.apache.camel.component.mock.MockEndpoint;
 import org.apache.camel.impl.DefaultCamelContext;
 import org.apache.camel.spi.Registry;
 import org.apache.camel.support.DefaultRegistry;
-import org.apache.camel.test.junit5.patterns.CreateCamelContextPerTestTrueTest;
 import org.junit.jupiter.api.Order;
 import org.junit.jupiter.api.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
-public class CamelTestSupporOneContextForAllTest extends CamelTestSupport {
-
-    private static final Logger LOG = LoggerFactory.getLogger(CreateCamelContextPerTestTrueTest.class);
+class CamelTestSupportOneContextForAllTest extends CamelTestSupport {
 
     private static final CamelContext CUSTOM_CONTEXT;
 
@@ -68,7 +63,7 @@ public class CamelTestSupporOneContextForAllTest extends CamelTestSupport {
 
     @Test
     @Order(1)
-    public void initContextTest() throws Exception {
+    void initContextTest() throws Exception {
         String expectedBody = "<matched/>";
 
         resultEndpoint.expectedBodiesReceived(expectedBody);
@@ -82,7 +77,7 @@ public class CamelTestSupporOneContextForAllTest extends CamelTestSupport {
 
     @Test
     @Order(2)
-    public void stopNotEnabledTest() throws Exception {
+    void stopNotEnabledTest() throws Exception {
         String expectedBody = "<matched/>";
 
         resultEndpoint.expectedBodiesReceived(expectedBody);
@@ -105,16 +100,14 @@ public class CamelTestSupporOneContextForAllTest extends CamelTestSupport {
 
     private static class MockContext extends DefaultCamelContext {
 
-        boolean initialized;
+        private boolean initialized;
 
         @Override
         protected Registry createRegistry() {
             if (initialized) {
                 throw new UnsupportedOperationException();
             }
-            if (!initialized) {
-                initialized = true;
-            }
+            initialized = true;
             return new DefaultRegistry();
         }
 
diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/RoutesLoader.java b/core/camel-api/src/main/java/org/apache/camel/spi/RoutesLoader.java
index d2e09295299..72b39e4fc09 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/RoutesLoader.java
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/RoutesLoader.java
@@ -60,6 +60,9 @@ public interface RoutesLoader extends CamelContextAware {
         for (RoutesBuilder builder : builders) {
             getCamelContext().addRoutes(builder);
         }
+        for (RoutesBuilder builder : builders) {
+            getCamelContext().addTemplatedRoutes(builder);
+        }
     }
 
     /**
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/builder/RouteBuilder.java b/core/camel-core-model/src/main/java/org/apache/camel/builder/RouteBuilder.java
index a646aff17b9..aebce342988 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/builder/RouteBuilder.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/builder/RouteBuilder.java
@@ -619,7 +619,7 @@ public abstract class RouteBuilder extends BuilderSupport implements RoutesBuild
 
     @Override
     public void addTemplatedRoutesToCamelContext(CamelContext context) throws Exception {
-        populateTemplatedRoutes();
+        populateTemplatedRoutes(context);
     }
 
     @Override
@@ -740,7 +740,10 @@ public abstract class RouteBuilder extends BuilderSupport implements RoutesBuild
     }
 
     protected void populateTemplatedRoutes() throws Exception {
-        CamelContext camelContext = notNullCamelContext();
+        populateTemplatedRoutes(notNullCamelContext());
+    }
+
+    private void populateTemplatedRoutes(CamelContext camelContext) throws Exception {
         getTemplatedRouteCollection().setCamelContext(camelContext);
         camelContext.getExtension(Model.class).addRouteFromTemplatedRoutes(getTemplatedRouteCollection().getTemplatedRoutes());
     }
diff --git a/dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/XmlMainTemplatedRouteFromDifferentDSLTest.java b/dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/XmlMainTemplatedRouteFromDifferentDSLTest.java
new file mode 100644
index 00000000000..1315c3271a0
--- /dev/null
+++ b/dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/XmlMainTemplatedRouteFromDifferentDSLTest.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.xml.io;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.main.Main;
+import org.apache.camel.model.ModelCamelContext;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class XmlMainTemplatedRouteFromDifferentDSLTest {
+
+    @Test
+    void testMain() throws Exception {
+        Main main = new Main();
+        main.configure().addRoutesBuilder(new RouteBuilder() {
+            @Override
+            public void configure() {
+                templatedRoute("myTemplate")
+                        .routeId("my-route")
+                        .parameter("foo", "fooVal")
+                        .parameter("bar", "barVal");
+            }
+        });
+        main.configure().withRoutesIncludePattern("org/apache/camel/main/xml/camel-my-route-template.xml");
+        main.start();
+
+        CamelContext context = main.getCamelContext();
+        assertEquals(1, context.adapt(ModelCamelContext.class).getRouteDefinitions().size());
+        assertEquals("my-route", context.adapt(ModelCamelContext.class).getRouteDefinitions().get(0).getId());
+
+        MockEndpoint mock = context.getEndpoint("mock:barVal", MockEndpoint.class);
+        mock.expectedBodiesReceived("Hello Camel");
+
+        ProducerTemplate template = context.createProducerTemplate();
+        template.sendBody("direct:fooVal", "Hello Camel");
+
+        mock.assertIsSatisfied();
+
+        main.stop();
+    }
+}
diff --git a/dsl/camel-xml-io-dsl/src/test/resources/org/apache/camel/main/xml/camel-my-route-template.xml b/dsl/camel-xml-io-dsl/src/test/resources/org/apache/camel/main/xml/camel-my-route-template.xml
new file mode 100644
index 00000000000..7eeb87e756d
--- /dev/null
+++ b/dsl/camel-xml-io-dsl/src/test/resources/org/apache/camel/main/xml/camel-my-route-template.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<routeTemplates id="camel" xmlns="http://camel.apache.org/schema/spring">
+    <routeTemplate id="myTemplate">
+        <templateParameter name="foo"/>
+        <templateParameter name="bar"/>
+        <route>
+            <from uri="direct:{{foo}}"/>
+            <to uri="mock:{{bar}}"/>
+        </route>
+    </routeTemplate>
+</routeTemplates>