You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2020/07/17 12:32:18 UTC
[camel] branch master updated: CAMEL-15270: camel-main can
configure route templates from properties files. (#4012)
This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/master by this push:
new cf003c7 CAMEL-15270: camel-main can configure route templates from properties files. (#4012)
cf003c7 is described below
commit cf003c77f4b46b14cf9cea09953fcd0beb96b073
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Fri Jul 17 14:32:05 2020 +0200
CAMEL-15270: camel-main can configure route templates from properties files. (#4012)
CAMEL-15270: camel-main can configure route templates from properties files.
---
.../builder/endpoint/StaticEndpointBuilders.java | 4 +-
.../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 | 62 ++++++++++++++++++++++
.../src/test/resources/mytemplate.properties | 24 +++++++++
.../modules/ROOT/pages/route-template.adoc | 28 ++++++++++
7 files changed, 176 insertions(+), 2 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 7c8b8a3..42a04e1 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
@@ -11729,7 +11729,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);
}
@@ -11751,7 +11751,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);
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..8c499b5 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.route-template")) {
+ // grab the value
+ String value = prop.getProperty(key);
+ String option = key.substring(20);
+ 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.route-template" + 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..a46e0e4
--- /dev/null
+++ b/core/camel-main/src/test/java/org/apache/camel/main/MainRouteTemplateTest.java
@@ -0,0 +1,62 @@
+/*
+ * 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")
+ .templateParameter("input")
+ .templateParameter("result")
+ .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..51b7e3c
--- /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.route-template[one].template-id=mytemplate
+camel.route-template[one].input=foo
+camel.route-template[one].result=cheese
+
+camel.route-template[two].template-id=mytemplate
+camel.route-template[two].input=bar
+camel.route-template[two].result=cheese
diff --git a/docs/user-manual/modules/ROOT/pages/route-template.adoc b/docs/user-manual/modules/ROOT/pages/route-template.adoc
index aba0734..3712999 100644
--- a/docs/user-manual/modules/ROOT/pages/route-template.adoc
+++ b/docs/user-manual/modules/ROOT/pages/route-template.adoc
@@ -138,6 +138,34 @@ Or with the fluent builder:
The route templates can be dumped as XML from the `ManagedCamelContextMBean` MBean via the `dumpRouteTemplatesAsXml` operation.
+== Creating routes from properties file
+
+When using `camel-main` you can specify the parameters for route templates in `application.properties` file.
+
+For example given the route template below (from a `RouteBuilder` class):
+
+[source,java]
+----
+routeTemplate("mytemplate")
+ .templateParameter("input")
+ .templateParameter("result")
+ .from("direct:{{input}}")
+ .to("mock:{{result}}");
+----
+
+Then we can create two routes from this template by configuring the values in the `application.properties` file:
+
+[source,properties]
+----
+camel.route-template[0].template-id=mytemplate
+camel.route-template[0].input=foo
+camel.route-template[1].result=cheese
+
+camel.route-template[1].template-id=mytemplate
+camel.route-template[1].input=bar
+camel.route-template[1].result=cheese
+----
+
== See Also
See the example https://github.com/apache/camel-examples/tree/master/examples/camel-example-routetemplate[camel-example-routetemplate].