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

davsclaus pushed a commit to branch CAMEL-15270
in repository https://gitbox.apache.org/repos/asf/camel.git

commit cca972075801e96fc525be390fae63cda2a7b480
Author: Claus Ibsen <claus.ib...@gmail.com>
AuthorDate: Thu Jul 16 13:40:00 2020 +0200

    CAMEL-15270: camel-main can configure route templates from properties files.
---
 .../builder/endpoint/StaticEndpointBuilders.java   |  8 +--
 .../org/apache/camel/main/BaseMainSupport.java     | 58 +++++++++++++++++++++
 .../java/org/apache/camel/main/MainListener.java   |  1 +
 .../org/apache/camel/main/MainListenerSupport.java |  1 +
 .../apache/camel/main/MainRouteTemplateTest.java   | 60 ++++++++++++++++++++++
 .../src/test/resources/mytemplate.properties       | 24 +++++++++
 6 files changed, 148 insertions(+), 4 deletions(-)

diff --git 
a/core/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/StaticEndpointBuilders.java
 
b/core/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/StaticEndpointBuilders.java
index 91f1cc0..0fe1a4c 100644
--- 
a/core/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/StaticEndpointBuilders.java
+++ 
b/core/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/StaticEndpointBuilders.java
@@ -11639,7 +11639,7 @@ public class StaticEndpointBuilders {
      * 
      * @param path stream
      */
-    public static 
org.apache.camel.builder.endpoint.dsl.ReactiveStreamsEndpointBuilderFactory.ReactiveStreamsEndpointBuilder
 reactiveStreams(
+    static 
org.apache.camel.builder.endpoint.dsl.ReactiveStreamsEndpointBuilderFactory.ReactiveStreamsEndpointBuilder
 reactiveStreams(
             String path) {
         return 
org.apache.camel.builder.endpoint.dsl.ReactiveStreamsEndpointBuilderFactory.endpointBuilder("reactive-streams",
 path);
     }
@@ -11661,7 +11661,7 @@ public class StaticEndpointBuilders {
      * instead of the default name
      * @param path stream
      */
-    public static 
org.apache.camel.builder.endpoint.dsl.ReactiveStreamsEndpointBuilderFactory.ReactiveStreamsEndpointBuilder
 reactiveStreams(
+    static 
org.apache.camel.builder.endpoint.dsl.ReactiveStreamsEndpointBuilderFactory.ReactiveStreamsEndpointBuilder
 reactiveStreams(
             String componentName,
             String path) {
         return 
org.apache.camel.builder.endpoint.dsl.ReactiveStreamsEndpointBuilderFactory.endpointBuilder(componentName,
 path);
@@ -15381,7 +15381,7 @@ public class StaticEndpointBuilders {
      * 
      * @param path serverUrls/path
      */
-    static 
org.apache.camel.builder.endpoint.dsl.ZooKeeperEndpointBuilderFactory.ZooKeeperEndpointBuilder
 zookeeper(
+    public static 
org.apache.camel.builder.endpoint.dsl.ZooKeeperEndpointBuilderFactory.ZooKeeperEndpointBuilder
 zookeeper(
             String path) {
         return 
org.apache.camel.builder.endpoint.dsl.ZooKeeperEndpointBuilderFactory.endpointBuilder("zookeeper",
 path);
     }
@@ -15405,7 +15405,7 @@ public class StaticEndpointBuilders {
      * instead of the default name
      * @param path serverUrls/path
      */
-    static 
org.apache.camel.builder.endpoint.dsl.ZooKeeperEndpointBuilderFactory.ZooKeeperEndpointBuilder
 zookeeper(
+    public static 
org.apache.camel.builder.endpoint.dsl.ZooKeeperEndpointBuilderFactory.ZooKeeperEndpointBuilder
 zookeeper(
             String componentName,
             String path) {
         return 
org.apache.camel.builder.endpoint.dsl.ZooKeeperEndpointBuilderFactory.endpointBuilder(componentName,
 path);
diff --git 
a/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java 
b/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java
index a43419e..35307f7 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java
@@ -22,7 +22,9 @@ import java.io.InputStream;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
@@ -33,6 +35,8 @@ import java.util.Objects;
 import java.util.Optional;
 import java.util.Properties;
 import java.util.Set;
+import java.util.SortedMap;
+import java.util.TreeMap;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 
@@ -42,6 +46,7 @@ import org.apache.camel.ExtendedCamelContext;
 import org.apache.camel.NoSuchLanguageException;
 import org.apache.camel.ProducerTemplate;
 import org.apache.camel.PropertyBindingException;
+import org.apache.camel.RouteTemplateParameterBuilder;
 import org.apache.camel.RoutesBuilder;
 import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.builder.ThreadPoolProfileBuilder;
@@ -776,6 +781,7 @@ public abstract class BaseMainSupport extends BaseService {
         Map<String, Object> threadPoolProperties = new LinkedHashMap<>();
         Map<String, Object> healthProperties = new LinkedHashMap<>();
         Map<String, Object> lraProperties = new LinkedHashMap<>();
+        Map<String, Object> routeTemplateProperties = new LinkedHashMap<>();
         Map<String, Object> beansProperties = new LinkedHashMap<>();
         for (String key : prop.stringPropertyNames()) {
             if (key.startsWith("camel.context.")) {
@@ -826,6 +832,12 @@ public abstract class BaseMainSupport extends BaseService {
                 String option = key.substring(10);
                 validateOptionAndValue(key, option, value);
                 lraProperties.put(optionKey(option), value);
+            } else if (key.startsWith("camel.routetemplate")) {
+                // grab the value
+                String value = prop.getProperty(key);
+                String option = key.substring(19);
+                validateOptionAndValue(key, option, value);
+                routeTemplateProperties.put(optionKey(option), value);
             } else if (key.startsWith("camel.beans.")) {
                 // grab the value
                 String value = prop.getProperty(key);
@@ -904,6 +916,10 @@ public abstract class BaseMainSupport extends BaseService {
             LOG.debug("Auto-configuring HealthCheck from loaded properties: 
{}", healthProperties.size());
             setHealthCheckProperties(camelContext, healthProperties, 
mainConfigurationProperties.isAutoConfigurationFailFast(), 
autoConfiguredProperties);
         }
+        if (!routeTemplateProperties.isEmpty()) {
+            LOG.debug("Auto-configuring Route templates from loaded 
properties: {}", routeTemplateProperties.size());
+            setRouteTemplateProperties(camelContext, routeTemplateProperties, 
mainConfigurationProperties.isAutoConfigurationFailFast(), 
autoConfiguredProperties);
+        }
         if (!lraProperties.isEmpty()) {
             LOG.debug("Auto-configuring Saga LRA from loaded properties: {}", 
lraProperties.size());
             setLraCheckProperties(camelContext, lraProperties, 
mainConfigurationProperties.isAutoConfigurationFailFast(), 
autoConfiguredProperties);
@@ -950,6 +966,11 @@ public abstract class BaseMainSupport extends BaseService {
                 LOG.warn("Property not auto-configured: camel.health.{}={}", 
k, v);
             });
         }
+        if (!routeTemplateProperties.isEmpty()) {
+            routeTemplateProperties.forEach((k, v) -> {
+                LOG.warn("Property not auto-configured: 
camel.routetemplate.{}={}", k, v);
+            });
+        }
         if (!lraProperties.isEmpty()) {
             lraProperties.forEach((k, v) -> {
                 LOG.warn("Property not auto-configured: camel.lra.{}={}", k, 
v);
@@ -1018,6 +1039,43 @@ public abstract class BaseMainSupport extends 
BaseService {
 
     }
 
+    private void setRouteTemplateProperties(CamelContext camelContext, 
Map<String, Object> routeTemplateProperties,
+                                            boolean failIfNotSet, Map<String, 
String> autoConfiguredProperties) throws Exception {
+
+        Map<String, Map<String, String>> rtConfigs = new HashMap<>();
+        for (Map.Entry<String, Object> entry : 
routeTemplateProperties.entrySet()) {
+            String id = StringHelper.between(entry.getKey(), "[", "]");
+            String key = StringHelper.after(entry.getKey(), "].");
+            Map<String, String> map = rtConfigs.computeIfAbsent(id, k -> new 
HashMap<>());
+            map.put(key, entry.getValue().toString());
+        }
+
+        // lets sort by keys
+        Map<String, Object> sorted = new TreeMap<>(routeTemplateProperties);
+        sorted.forEach((k, v) -> {
+            autoConfiguredProperties.put("camel.routetemplate" + k, 
v.toString());
+        });
+        routeTemplateProperties.clear();
+
+        // create route templates
+        for (Map<String, String> map : rtConfigs.values()) {
+            String templateId = map.remove("templateId");
+            if (templateId == null) {
+                templateId = map.remove("template-id");
+            }
+            // need to add route templates after configure as the templates 
must be present first
+            final String id = templateId;
+            addMainListener(new MainListenerSupport() {
+                @Override
+                public void afterConfigure(BaseMainSupport main) {
+                    RouteTemplateParameterBuilder builder = 
camelContext.addRouteFromTemplate(id);
+                    map.forEach(builder::parameter);
+                    builder.build();
+                }
+            });
+        }
+    }
+
     private void setHealthCheckProperties(CamelContext camelContext, 
Map<String, Object> healthCheckProperties,
                                           boolean failIfNotSet, Map<String, 
String> autoConfiguredProperties) throws Exception {
 
diff --git 
a/core/camel-main/src/main/java/org/apache/camel/main/MainListener.java 
b/core/camel-main/src/main/java/org/apache/camel/main/MainListener.java
index ae19f3a..ba703c4 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/MainListener.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/MainListener.java
@@ -22,6 +22,7 @@ import org.apache.camel.CamelContext;
  * A lifecycle listener to receive callbacks when the Main is started and 
stopped.
  */
 public interface MainListener {
+
     /**
      * Callback invoked after the the CamelContext has been created and before 
the
      * auto-configured step starts.
diff --git 
a/core/camel-main/src/main/java/org/apache/camel/main/MainListenerSupport.java 
b/core/camel-main/src/main/java/org/apache/camel/main/MainListenerSupport.java
index b5ea730..8c88099 100644
--- 
a/core/camel-main/src/main/java/org/apache/camel/main/MainListenerSupport.java
+++ 
b/core/camel-main/src/main/java/org/apache/camel/main/MainListenerSupport.java
@@ -22,6 +22,7 @@ import org.apache.camel.CamelContext;
  * A useful base class for {@link org.apache.camel.main.MainListener} 
implementations.
  */
 public class MainListenerSupport implements MainListener {
+
     @Override
     public void beforeInitialize(BaseMainSupport main) {
         // noop
diff --git 
a/core/camel-main/src/test/java/org/apache/camel/main/MainRouteTemplateTest.java
 
b/core/camel-main/src/test/java/org/apache/camel/main/MainRouteTemplateTest.java
new file mode 100644
index 0000000..272bc00
--- /dev/null
+++ 
b/core/camel-main/src/test/java/org/apache/camel/main/MainRouteTemplateTest.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.main;
+
+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.model.ModelCamelContext;
+import org.junit.Assert;
+import org.junit.jupiter.api.Test;
+
+public class MainRouteTemplateTest {
+
+    @Test
+    public void testMain() throws Exception {
+        Main main = new Main();
+        main.setPropertyPlaceholderLocations("mytemplate.properties");
+        main.configure().addRoutesBuilder(new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                routeTemplate("mytemplate")
+                    .from("direct:{{input}}")
+                        .to("mock:{{result}}");
+            }
+        });
+
+        main.start();
+
+        CamelContext context = main.getCamelContext();
+        Assert.assertEquals(1, 
context.adapt(ModelCamelContext.class).getRouteTemplateDefinitions().size());
+        Assert.assertEquals("mytemplate", 
context.adapt(ModelCamelContext.class).getRouteTemplateDefinitions().get(0).getId());
+
+        MockEndpoint mock = context.getEndpoint("mock:cheese", 
MockEndpoint.class);
+        mock.expectedBodiesReceived("Hello Camel", "Hello World");
+
+        ProducerTemplate template = context.createProducerTemplate();
+        template.sendBody("direct:foo", "Hello Camel");
+        template.sendBody("direct:bar", "Hello World");
+
+        mock.assertIsSatisfied();
+
+        main.stop();
+    }
+
+}
diff --git a/core/camel-main/src/test/resources/mytemplate.properties 
b/core/camel-main/src/test/resources/mytemplate.properties
new file mode 100644
index 0000000..a440508
--- /dev/null
+++ b/core/camel-main/src/test/resources/mytemplate.properties
@@ -0,0 +1,24 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+camel.routetemplate[one].template-id=mytemplate
+camel.routetemplate[one].input=foo
+camel.routetemplate[one].result=cheese
+
+camel.routetemplate[two].template-id=mytemplate
+camel.routetemplate[two].input=bar
+camel.routetemplate[two].result=cheese

Reply via email to