You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by lb...@apache.org on 2020/09/29 10:47:22 UTC
[camel] branch master updated: CAMEL-15590: route templates: add an
hook to further customize the RouteDefinition computed out of a template
This is an automated email from the ASF dual-hosted git repository.
lburgazzoli 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 5029d32 CAMEL-15590: route templates: add an hook to further customize the RouteDefinition computed out of a template
5029d32 is described below
commit 5029d32302fbd5e8d2688b82b0dc66637633ef62
Author: Luca Burgazzoli <lb...@gmail.com>
AuthorDate: Tue Sep 29 11:30:19 2020 +0200
CAMEL-15590: route templates: add an hook to further customize the RouteDefinition computed out of a template
---
.../org/apache/camel/impl/DefaultCamelContext.java | 6 +-
.../java/org/apache/camel/impl/DefaultModel.java | 65 +++++++---
.../camel/impl/lw/LightweightCamelContext.java | 5 +
.../main/java/org/apache/camel/model/Model.java | 9 ++
.../camel/model/RouteTemplateDefinition.java | 5 +
.../camel/builder/RouteTemplateConverterTest.java | 136 +++++++++++++++++++++
6 files changed, 205 insertions(+), 21 deletions(-)
diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultCamelContext.java b/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
index c4ead09..b6d16d9 100644
--- a/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
+++ b/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
@@ -183,6 +183,11 @@ public class DefaultCamelContext extends SimpleCamelContext implements ModelCame
}
@Override
+ public void addRouteTemplateDefinitionConverter(String templateIdPattern, RouteTemplateDefinition.Converter converter) {
+ model.addRouteTemplateDefinitionConverter(templateIdPattern, converter);
+ }
+
+ @Override
public String addRouteFromTemplate(String routeId, String routeTemplateId, Map<String, Object> parameters)
throws Exception {
return model.addRouteFromTemplate(routeId, routeTemplateId, parameters);
@@ -487,5 +492,4 @@ public class DefaultCamelContext extends SimpleCamelContext implements ModelCame
? new TransformerKey(def.getScheme())
: new TransformerKey(new DataType(def.getFromType()), new DataType(def.getToType()));
}
-
}
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 bdaf469..f545d28 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
@@ -46,6 +46,7 @@ import org.apache.camel.model.cloud.ServiceCallConfigurationDefinition;
import org.apache.camel.model.rest.RestDefinition;
import org.apache.camel.model.transformer.TransformerDefinition;
import org.apache.camel.model.validator.ValidatorDefinition;
+import org.apache.camel.util.AntPathMatcher;
public class DefaultModel implements Model {
@@ -55,6 +56,7 @@ public class DefaultModel implements Model {
private final List<RouteDefinition> routeDefinitions = new ArrayList<>();
private final List<RouteTemplateDefinition> routeTemplateDefinitions = new ArrayList<>();
private final List<RestDefinition> restDefinitions = new ArrayList<>();
+ private final Map<String, RouteTemplateDefinition.Converter> routeTemplateConverters = new ConcurrentHashMap<>();
private Map<String, DataFormatDefinition> dataFormats = new HashMap<>();
private List<TransformerDefinition> transformers = new ArrayList<>();
private List<ValidatorDefinition> validators = new ArrayList<>();
@@ -68,6 +70,15 @@ public class DefaultModel implements Model {
this.camelContext = camelContext;
}
+ protected static <T> T lookup(CamelContext context, String ref, Class<T> type) {
+ try {
+ return context.getRegistry().lookupByNameAndType(ref, type);
+ } catch (Exception e) {
+ // need to ignore not same type and return it as null
+ return null;
+ }
+ }
+
public CamelContext getCamelContext() {
return camelContext;
}
@@ -194,6 +205,11 @@ public class DefaultModel implements Model {
}
@Override
+ public void addRouteTemplateDefinitionConverter(String templateIdPattern, RouteTemplateDefinition.Converter converter) {
+ routeTemplateConverters.put(templateIdPattern, converter);
+ }
+
+ @Override
public String addRouteFromTemplate(final String routeId, final String routeTemplateId, final Map<String, Object> parameters)
throws Exception {
RouteTemplateDefinition target = null;
@@ -208,7 +224,7 @@ public class DefaultModel implements Model {
}
StringJoiner templatesBuilder = new StringJoiner(", ");
- final Map<String, Object> prop = new HashMap();
+ final Map<String, Object> prop = new HashMap<>();
// include default values first from the template (and validate that we have inputs for all required parameters)
if (target.getTemplateParameters() != null) {
for (RouteTemplateParameterDefinition temp : target.getTemplateParameters()) {
@@ -232,7 +248,25 @@ public class DefaultModel implements Model {
prop.putAll(parameters);
}
- RouteDefinition def = target.asRouteDefinition();
+ RouteTemplateDefinition.Converter converter = RouteTemplateDefinition::asRouteDefinition;
+
+ for (Map.Entry<String, RouteTemplateDefinition.Converter> entry : routeTemplateConverters.entrySet()) {
+ final String key = entry.getKey();
+ final String templateId = target.getId();
+
+ if ("*".equals(key) || templateId.equals(key)) {
+ converter = entry.getValue();
+ break;
+ } else if (AntPathMatcher.INSTANCE.match(key, templateId)) {
+ converter = entry.getValue();
+ break;
+ } else if (templateId.matches(key)) {
+ converter = entry.getValue();
+ break;
+ }
+ }
+
+ RouteDefinition def = converter.apply(target);
if (routeId != null) {
def.setId(routeId);
}
@@ -411,18 +445,13 @@ public class DefaultModel implements Model {
}
@Override
- public void setDataFormats(Map<String, DataFormatDefinition> dataFormats) {
- this.dataFormats = dataFormats;
- }
-
- @Override
public Map<String, DataFormatDefinition> getDataFormats() {
return dataFormats;
}
@Override
- public void setTransformers(List<TransformerDefinition> transformers) {
- this.transformers = transformers;
+ public void setDataFormats(Map<String, DataFormatDefinition> dataFormats) {
+ this.dataFormats = dataFormats;
}
@Override
@@ -431,8 +460,8 @@ public class DefaultModel implements Model {
}
@Override
- public void setValidators(List<ValidatorDefinition> validators) {
- this.validators = validators;
+ public void setTransformers(List<TransformerDefinition> transformers) {
+ this.transformers = transformers;
}
@Override
@@ -441,6 +470,11 @@ public class DefaultModel implements Model {
}
@Override
+ public void setValidators(List<ValidatorDefinition> validators) {
+ this.validators = validators;
+ }
+
+ @Override
public void setRouteFilterPattern(String include, String exclude) {
setRouteFilter(RouteFilters.filterByPattern(include, exclude));
}
@@ -462,13 +496,4 @@ public class DefaultModel implements Model {
return camelContext.isStarted() && !camelContext.isStarting();
}
- protected static <T> T lookup(CamelContext context, String ref, Class<T> type) {
- try {
- return context.getRegistry().lookupByNameAndType(ref, type);
- } catch (Exception e) {
- // need to ignore not same type and return it as null
- return null;
- }
- }
-
}
diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightCamelContext.java b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightCamelContext.java
index f2fc22d..3fc21ce 100644
--- a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightCamelContext.java
+++ b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightCamelContext.java
@@ -1554,6 +1554,11 @@ public class LightweightCamelContext implements ExtendedCamelContext, CatalogCam
}
@Override
+ public void addRouteTemplateDefinitionConverter(String templateIdPattern, RouteTemplateDefinition.Converter converter) {
+ getModelCamelContext().addRouteTemplateDefinitionConverter(templateIdPattern, converter);
+ }
+
+ @Override
public String addRouteFromTemplate(String routeId, String routeTemplateId, Map<String, Object> parameters)
throws Exception {
return getModelCamelContext().addRouteFromTemplate(routeId, routeTemplateId, parameters);
diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/model/Model.java b/core/camel-core-engine/src/main/java/org/apache/camel/model/Model.java
index 956fab8..4981706 100644
--- a/core/camel-core-engine/src/main/java/org/apache/camel/model/Model.java
+++ b/core/camel-core-engine/src/main/java/org/apache/camel/model/Model.java
@@ -156,6 +156,15 @@ public interface Model {
void removeRouteTemplateDefinition(RouteTemplateDefinition routeTemplateDefinition) throws Exception;
/**
+ * Add a converter to translate a {@link RouteTemplateDefinition} to a {@link RouteDefinition}.
+ *
+ * @param templateIdPattern the route template ut to whom a pattern should eb applied
+ * @param converter the {@link RouteTemplateDefinition.Converter} used to convert a
+ * {@link RouteTemplateDefinition} to a {@link RouteDefinition}
+ */
+ void addRouteTemplateDefinitionConverter(String templateIdPattern, RouteTemplateDefinition.Converter converter);
+
+ /**
* Adds a new route from a given route template
*
* @param routeId the id of the new route to add (optional)
diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/model/RouteTemplateDefinition.java b/core/camel-core-engine/src/main/java/org/apache/camel/model/RouteTemplateDefinition.java
index 5871cd0..c4c1252 100644
--- a/core/camel-core-engine/src/main/java/org/apache/camel/model/RouteTemplateDefinition.java
+++ b/core/camel-core-engine/src/main/java/org/apache/camel/model/RouteTemplateDefinition.java
@@ -30,6 +30,7 @@ import org.apache.camel.Endpoint;
import org.apache.camel.builder.EndpointConsumerBuilder;
import org.apache.camel.spi.AsEndpointUri;
import org.apache.camel.spi.Metadata;
+import org.apache.camel.util.function.ThrowingFunction;
/**
* Defines a route template (parameterized routes)
@@ -213,4 +214,8 @@ public class RouteTemplateDefinition extends OptionalIdentifiedDefinition {
return copy;
}
+
+ @FunctionalInterface
+ public interface Converter extends ThrowingFunction<RouteTemplateDefinition, RouteDefinition, Exception> {
+ }
}
diff --git a/core/camel-core/src/test/java/org/apache/camel/builder/RouteTemplateConverterTest.java b/core/camel-core/src/test/java/org/apache/camel/builder/RouteTemplateConverterTest.java
new file mode 100644
index 0000000..c884969
--- /dev/null
+++ b/core/camel-core/src/test/java/org/apache/camel/builder/RouteTemplateConverterTest.java
@@ -0,0 +1,136 @@
+/*
+ * 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.builder;
+
+import java.util.stream.IntStream;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.model.FromDefinition;
+import org.apache.camel.model.RouteDefinition;
+import org.apache.camel.model.RouteTemplateDefinition;
+import org.junit.jupiter.api.Test;
+
+import static org.apache.camel.util.CollectionHelper.mapOf;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class RouteTemplateConverterTest extends ContextTestSupport {
+ @Test
+ public void testCreateRouteFromRouteTemplateWithDefaultConverter() throws Exception {
+ context.addRouteTemplateDefinitionConverter("myTemplate1", RouteTemplateDefinition::asRouteDefinition);
+ context.addRouteFromTemplate("first", "myTemplate1", mapOf("foo", "one", "bar", "cheese"));
+
+ assertEquals(1, context.getRouteDefinitions().size());
+ assertEquals(1, context.getRoutes().size());
+
+ assertEquals("direct:{{foo}}", context.getRouteDefinition("first").getInput().getEndpointUri());
+ assertEquals("direct://one", context.getRoute("first").getEndpoint().getEndpointUri());
+ }
+
+ @Test
+ public void testCreateRouteFromRouteTemplateWithCustomConverter() throws Exception {
+ context.addRouteTemplateDefinitionConverter("myTemplate1", template -> {
+ final RouteDefinition def = template.asRouteDefinition();
+ final String inUri = def.getInput().getEndpointUri();
+ def.setInput(null);
+ def.setInput(new FromDefinition(inUri + "?timeout=60s"));
+ return def;
+ });
+
+ context.addRouteFromTemplate("first", "myTemplate1", mapOf("foo", "one", "bar", "cheese"));
+
+ assertEquals(1, context.getRouteDefinitions().size());
+ assertEquals(1, context.getRoutes().size());
+
+ assertEquals("direct:{{foo}}?timeout=60s", context.getRouteDefinition("first").getInput().getEndpointUri());
+ assertEquals("direct://one?timeout=60s", context.getRoute("first").getEndpoint().getEndpointUri());
+ }
+
+ @Test
+ public void testCreateRouteFromRouteTemplateWithCustomConverterPatter() throws Exception {
+ context.addRouteTemplateDefinitionConverter("myTemplate[12]", template -> {
+ final RouteDefinition def = template.asRouteDefinition();
+ final String inUri = def.getInput().getEndpointUri();
+ def.setInput(null);
+ def.setInput(new FromDefinition(inUri + "?timeout=60s"));
+ return def;
+ });
+
+ IntStream.of(1, 2, 3).mapToObj(Integer::toString).forEach(index -> {
+ try {
+ context.addRouteFromTemplate(index, "myTemplate" + index, mapOf("foo", index, "bar", "cheese"));
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ });
+
+ assertEquals(3, context.getRouteDefinitions().size());
+ assertEquals(3, context.getRoutes().size());
+
+ assertEquals("direct:{{foo}}?timeout=60s", context.getRouteDefinition("1").getInput().getEndpointUri());
+ assertEquals("direct://1?timeout=60s", context.getRoute("1").getEndpoint().getEndpointUri());
+ assertEquals("direct:{{foo}}?timeout=60s", context.getRouteDefinition("2").getInput().getEndpointUri());
+ assertEquals("direct://2?timeout=60s", context.getRoute("2").getEndpoint().getEndpointUri());
+ assertEquals("direct:{{foo}}", context.getRouteDefinition("3").getInput().getEndpointUri());
+ assertEquals("direct://3", context.getRoute("3").getEndpoint().getEndpointUri());
+ }
+
+ @Test
+ public void testCreateRouteFromRouteTemplateWithCustomConverterGlob() {
+ context.addRouteTemplateDefinitionConverter("*", template -> {
+ final RouteDefinition def = template.asRouteDefinition();
+ final String inUri = def.getInput().getEndpointUri();
+ def.setInput(null);
+ def.setInput(new FromDefinition(inUri + "?timeout=60s"));
+ return def;
+ });
+
+ IntStream.of(1, 2, 3).mapToObj(Integer::toString).forEach(index -> {
+ try {
+ context.addRouteFromTemplate(index, "myTemplate" + index, mapOf("foo", index, "bar", "cheese"));
+
+ assertEquals("direct:{{foo}}?timeout=60s", context.getRouteDefinition(index).getInput().getEndpointUri());
+ assertEquals("direct://" + index + "?timeout=60s", context.getRoute(index).getEndpoint().getEndpointUri());
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ });
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ routeTemplate("myTemplate1")
+ .templateParameter("foo")
+ .templateParameter("bar")
+ .from("direct:{{foo}}")
+ .to("mock:{{bar}}");
+ routeTemplate("myTemplate2")
+ .templateParameter("foo")
+ .templateParameter("bar")
+ .from("direct:{{foo}}")
+ .to("mock:{{bar}}");
+ routeTemplate("myTemplate3")
+ .templateParameter("foo")
+ .templateParameter("bar")
+ .from("direct:{{foo}}")
+ .to("mock:{{bar}}");
+ }
+ };
+ }
+}