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 2022/12/07 08:37:15 UTC
[camel] 01/04: CAMEL-18798/CAMEL-18771: Allow to configure nodePrefixId on route/routeTemplate to prefix all node IDs to make it easier to avoid clash with hardcoded IDs.
This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch prefixId
in repository https://gitbox.apache.org/repos/asf/camel.git
commit 6098712077423bedb8b5d21d7aaa3d9fb2516a27
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Wed Dec 7 07:36:51 2022 +0100
CAMEL-18798/CAMEL-18771: Allow to configure nodePrefixId on route/routeTemplate to prefix all node IDs to make it easier to avoid clash with hardcoded IDs.
---
.../camel/catalog/models/templatedRoute.json | 1 +
.../main/java/org/apache/camel/CamelContext.java | 35 ++++
.../org/apache/camel/RouteTemplateContext.java | 8 +-
.../camel/impl/engine/SimpleCamelContext.java | 13 ++
.../org/apache/camel/impl/DefaultCamelContext.java | 24 ++-
.../java/org/apache/camel/impl/DefaultModel.java | 28 ++-
.../camel/impl/lw/LightweightCamelContext.java | 13 ++
.../impl/lw/LightweightRuntimeCamelContext.java | 13 ++
.../org/apache/camel/model/templatedRoute.json | 1 +
.../camel/builder/TemplatedRouteBuilder.java | 13 +-
.../main/java/org/apache/camel/model/Model.java | 30 ++++
.../camel/model/OptionalIdentifiedDefinition.java | 22 ++-
.../apache/camel/model/ProcessorDefinition.java | 17 ++
.../org/apache/camel/model/RouteDefinition.java | 29 +++
.../apache/camel/model/RouteDefinitionHelper.java | 38 ++++
.../camel/model/TemplatedRouteDefinition.java | 20 +++
.../camel/builder/RouteTemplatePrefixIdTest.java | 194 +++++++++++++++++++++
.../processor/RouteNodePrefixIdDuplicateTest.java | 58 ++++++
.../camel/processor/RouteNodePrefixIdTest.java | 70 ++++++++
.../camel/main/MainTemplatedRoutePrefixIdTest.java | 77 ++++++++
.../apache/camel/support/LocalBeanRegistry.java | 6 +-
.../java/org/apache/camel/xml/in/ModelParser.java | 2 +
22 files changed, 698 insertions(+), 14 deletions(-)
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/templatedRoute.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/templatedRoute.json
index cfa496c210f..fe5d87f4f42 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/templatedRoute.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/templatedRoute.json
@@ -14,6 +14,7 @@
"properties": {
"routeTemplateRef": { "kind": "attribute", "displayName": "Route Template Ref", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the id of the route template to use to build the route." },
"routeId": { "kind": "attribute", "displayName": "Route Id", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the id of the route built from the route template." },
+ "prefixId": { "kind": "attribute", "displayName": "Prefix Id", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets a prefix to use when assigning route and node IDs." },
"parameter": { "kind": "element", "displayName": "Parameter", "required": false, "type": "array", "javaType": "java.util.List<org.apache.camel.model.TemplatedRouteParameterDefinition>", "deprecated": false, "autowired": false, "secret": false, "description": "Adds an input parameter of the template to build the route" },
"bean": { "kind": "element", "displayName": "Bean", "required": false, "type": "array", "javaType": "java.util.List<org.apache.camel.model.TemplatedRouteBeanDefinition>", "deprecated": false, "autowired": false, "secret": false, "description": "Adds a local bean as input of the template to build the route" }
}
diff --git a/core/camel-api/src/main/java/org/apache/camel/CamelContext.java b/core/camel-api/src/main/java/org/apache/camel/CamelContext.java
index fda8bccb99a..be6a61d50f8 100644
--- a/core/camel-api/src/main/java/org/apache/camel/CamelContext.java
+++ b/core/camel-api/src/main/java/org/apache/camel/CamelContext.java
@@ -635,6 +635,24 @@ public interface CamelContext extends CamelContextLifecycle, RuntimeConfiguratio
*/
String addRouteFromTemplate(String routeId, String routeTemplateId, Map<String, Object> parameters) throws Exception;
+ /**
+ * Adds a new route from a given route template.
+ *
+ * Camel end users should favour using {@link org.apache.camel.builder.TemplatedRouteBuilder} which is a fluent
+ * builder with more functionality than this API.
+ *
+ * @param routeId the id of the new route to add (optional)
+ * @param routeTemplateId the id of the route template (mandatory)
+ * @param prefixId prefix to use when assigning route and node IDs (optional)
+ * @param parameters parameters to use for the route template when creating the new route
+ * @return the id of the route added (for example when an id was auto assigned)
+ * @throws Exception is thrown if error creating and adding the new route
+ */
+ String addRouteFromTemplate(
+ String routeId, String routeTemplateId, String prefixId,
+ Map<String, Object> parameters)
+ throws Exception;
+
/**
* Adds a new route from a given route template.
*
@@ -650,6 +668,23 @@ public interface CamelContext extends CamelContextLifecycle, RuntimeConfiguratio
String addRouteFromTemplate(String routeId, String routeTemplateId, RouteTemplateContext routeTemplateContext)
throws Exception;
+ /**
+ * Adds a new route from a given route template.
+ *
+ * Camel end users should favour using {@link org.apache.camel.builder.TemplatedRouteBuilder} which is a fluent
+ * builder with more functionality than this API.
+ *
+ * @param routeId the id of the new route to add (optional)
+ * @param routeTemplateId the id of the route template (mandatory)
+ * @param prefixId prefix to use when assigning route and node IDs (optional)
+ * @param routeTemplateContext the route template context (mandatory)
+ * @return the id of the route added (for example when an id was auto assigned)
+ * @throws Exception is thrown if error creating and adding the new route
+ */
+ String addRouteFromTemplate(
+ String routeId, String routeTemplateId, String prefixId, RouteTemplateContext routeTemplateContext)
+ throws Exception;
+
/**
* Removes the route templates matching the pattern
*
diff --git a/core/camel-api/src/main/java/org/apache/camel/RouteTemplateContext.java b/core/camel-api/src/main/java/org/apache/camel/RouteTemplateContext.java
index fa2c77dc2e7..855353d44b9 100644
--- a/core/camel-api/src/main/java/org/apache/camel/RouteTemplateContext.java
+++ b/core/camel-api/src/main/java/org/apache/camel/RouteTemplateContext.java
@@ -39,7 +39,7 @@ public interface RouteTemplateContext extends HasCamelContext {
/**
* Binds the bean to the repository (if possible).
*
- * If the bean is {@link CamelContextAware} then the registry will automatic inject the context if possible.
+ * If the bean is {@link CamelContextAware} then the registry will automatically inject the context if possible.
*
* @param id the id of the bean
* @param bean the bean
@@ -53,7 +53,7 @@ public interface RouteTemplateContext extends HasCamelContext {
* <p/>
* Binding by id and type allows to bind multiple entries with the same id but with different type.
*
- * If the bean is {@link CamelContextAware} then the registry will automatic inject the context if possible.
+ * If the bean is {@link CamelContextAware} then the registry will automatically inject the context if possible.
*
* @param id the id of the bean
* @param type the type of the bean to associate the binding
@@ -69,7 +69,7 @@ public interface RouteTemplateContext extends HasCamelContext {
* <p/>
* Binding by id and type allows to bind multiple entries with the same id but with different type.
*
- * If the bean is {@link CamelContextAware} then the registry will automatic inject the context if possible.
+ * If the bean is {@link CamelContextAware} then the registry will automatically inject the context if possible.
*
* @param id the id of the bean
* @param type the type of the bean to associate the binding
@@ -84,7 +84,7 @@ public interface RouteTemplateContext extends HasCamelContext {
* <p/>
* Binding by id and type allows to bind multiple entries with the same id but with different type.
*
- * If the bean is {@link CamelContextAware} then the registry will automatic inject the context if possible.
+ * If the bean is {@link CamelContextAware} then the registry will automatically inject the context if possible.
*
* @param id the id of the bean
* @param type the type of the bean to associate the binding
diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java
index 690a87baced..16ddc3a347a 100644
--- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java
+++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java
@@ -704,12 +704,25 @@ public class SimpleCamelContext extends AbstractCamelContext {
throw new UnsupportedOperationException();
}
+ @Override
+ public String addRouteFromTemplate(String routeId, String routeTemplateId, String prefixId, Map<String, Object> parameters)
+ throws Exception {
+ throw new UnsupportedOperationException();
+ }
+
@Override
public String addRouteFromTemplate(String routeId, String routeTemplateId, RouteTemplateContext routeTemplateContext)
throws Exception {
throw new UnsupportedOperationException();
}
+ @Override
+ public String addRouteFromTemplate(
+ String routeId, String routeTemplateId, String prefixId, RouteTemplateContext routeTemplateContext)
+ throws Exception {
+ throw new UnsupportedOperationException();
+ }
+
@Override
public void removeRouteTemplates(String pattern) throws Exception {
throw new UnsupportedOperationException();
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 e9c2b30bc0e..54ab4d6ecdd 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
@@ -474,6 +474,15 @@ public class DefaultCamelContext extends SimpleCamelContext implements ModelCame
return model.addRouteFromTemplate(routeId, routeTemplateId, parameters);
}
+ @Override
+ public String addRouteFromTemplate(String routeId, String routeTemplateId, String prefixId, Map<String, Object> parameters)
+ throws Exception {
+ if (model == null && isLightweight()) {
+ throw new IllegalStateException("Access to model not supported in lightweight mode");
+ }
+ return model.addRouteFromTemplate(routeId, routeTemplateId, prefixId, parameters);
+ }
+
@Override
public String addRouteFromTemplate(String routeId, String routeTemplateId, RouteTemplateContext routeTemplateContext)
throws Exception {
@@ -483,6 +492,16 @@ public class DefaultCamelContext extends SimpleCamelContext implements ModelCame
return model.addRouteFromTemplate(routeId, routeTemplateId, routeTemplateContext);
}
+ @Override
+ public String addRouteFromTemplate(
+ String routeId, String routeTemplateId, String prefixId, RouteTemplateContext routeTemplateContext)
+ throws Exception {
+ if (model == null && isLightweight()) {
+ throw new IllegalStateException("Access to model not supported in lightweight mode");
+ }
+ return model.addRouteFromTemplate(routeId, routeTemplateId, prefixId, routeTemplateContext);
+ }
+
@Override
public void addRouteFromTemplatedRoute(TemplatedRouteDefinition templatedRouteDefinition)
throws Exception {
@@ -820,7 +839,8 @@ public class DefaultCamelContext extends SimpleCamelContext implements ModelCame
List<RouteDefinition> routeDefinitionsToRemove = null;
for (RouteDefinition routeDefinition : routeDefinitions) {
// assign ids to the routes and validate that the id's is all unique
- String duplicate = RouteDefinitionHelper.validateUniqueIds(routeDefinition, routeDefinitions);
+ String duplicate = RouteDefinitionHelper.validateUniqueIds(routeDefinition, routeDefinitions,
+ routeDefinition.getNodePrefixId());
if (duplicate != null) {
throw new FailedToStartRouteException(
routeDefinition.getId(),
@@ -900,6 +920,8 @@ public class DefaultCamelContext extends SimpleCamelContext implements ModelCame
// need to reset auto assigned ids, so there is no clash when creating routes
ProcessorDefinitionHelper.resetAllAutoAssignedNodeIds(routeDefinition);
+ // must re-init parent when created from a template
+ RouteDefinitionHelper.initParent(routeDefinition);
}
// Check if the route is included
if (includedRoute(routeDefinition)) {
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 48d8847cbff..2cac4a0903e 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
@@ -364,12 +364,30 @@ public class DefaultModel implements Model {
if (parameters != null) {
parameters.forEach(rtc::setParameter);
}
- return addRouteFromTemplate(routeId, routeTemplateId, rtc);
+ return addRouteFromTemplate(routeId, routeTemplateId, null, rtc);
}
@Override
+ public String addRouteFromTemplate(String routeId, String routeTemplateId, String prefixId, Map<String, Object> parameters)
+ throws Exception {
+ RouteTemplateContext rtc = new DefaultRouteTemplateContext(camelContext);
+ if (parameters != null) {
+ parameters.forEach(rtc::setParameter);
+ }
+ return addRouteFromTemplate(routeId, routeTemplateId, prefixId, rtc);
+ }
+
public String addRouteFromTemplate(String routeId, String routeTemplateId, RouteTemplateContext routeTemplateContext)
throws Exception {
+ return addRouteFromTemplate(routeId, routeTemplateId, null, routeTemplateContext);
+ }
+
+ @Override
+ public String addRouteFromTemplate(
+ String routeId, String routeTemplateId, String prefixId,
+ RouteTemplateContext routeTemplateContext)
+ throws Exception {
+
RouteTemplateDefinition target = null;
for (RouteTemplateDefinition def : routeTemplateDefinitions) {
if (routeTemplateId.equals(def.getId())) {
@@ -459,6 +477,9 @@ public class DefaultModel implements Model {
if (routeId != null) {
def.setId(routeId);
}
+ if (prefixId != null) {
+ def.setNodePrefixId(prefixId);
+ }
def.setTemplateParameters(prop);
def.setTemplateDefaultParameters(propDefaultValues);
def.setRouteTemplateContext(routeTemplateContext);
@@ -473,7 +494,7 @@ public class DefaultModel implements Model {
}
// assign ids to the routes and validate that the id's are all unique
- String duplicate = RouteDefinitionHelper.validateUniqueIds(def, routeDefinitions);
+ String duplicate = RouteDefinitionHelper.validateUniqueIds(def, routeDefinitions, prefixId);
if (duplicate != null) {
throw new FailedToCreateRouteFromTemplateException(
routeId, routeTemplateId,
@@ -740,6 +761,7 @@ public class DefaultModel implements Model {
public void addRouteFromTemplatedRoute(TemplatedRouteDefinition templatedRouteDefinition)
throws Exception {
ObjectHelper.notNull(templatedRouteDefinition, "templatedRouteDefinition");
+
final RouteTemplateContext routeTemplateContext = new DefaultRouteTemplateContext(camelContext);
// Load the parameters into the context
final List<TemplatedRouteParameterDefinition> parameters = templatedRouteDefinition.getParameters();
@@ -757,7 +779,7 @@ public class DefaultModel implements Model {
}
// Add the route
addRouteFromTemplate(templatedRouteDefinition.getRouteId(), templatedRouteDefinition.getRouteTemplateRef(),
- routeTemplateContext);
+ templatedRouteDefinition.getPrefixId(), routeTemplateContext);
}
@Override
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 0800e42775e..7fc6ace53ac 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
@@ -1961,12 +1961,25 @@ public class LightweightCamelContext implements ExtendedCamelContext, CatalogCam
return getModelCamelContext().addRouteFromTemplate(routeId, routeTemplateId, parameters);
}
+ @Override
+ public String addRouteFromTemplate(String routeId, String routeTemplateId, String prefixId, Map<String, Object> parameters)
+ throws Exception {
+ return getModelCamelContext().addRouteFromTemplate(routeId, routeTemplateId, prefixId, parameters);
+ }
+
@Override
public String addRouteFromTemplate(String routeId, String routeTemplateId, RouteTemplateContext routeTemplateContext)
throws Exception {
return getModelCamelContext().addRouteFromTemplate(routeId, routeTemplateId, routeTemplateContext);
}
+ @Override
+ public String addRouteFromTemplate(
+ String routeId, String routeTemplateId, String prefixId, RouteTemplateContext routeTemplateContext)
+ throws Exception {
+ return getModelCamelContext().addRouteFromTemplate(routeId, routeTemplateId, prefixId, routeTemplateContext);
+ }
+
@Override
public void addRouteFromTemplatedRoute(TemplatedRouteDefinition templatedRouteDefinition)
throws Exception {
diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightRuntimeCamelContext.java b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightRuntimeCamelContext.java
index aec0eda6796..122a6237168 100644
--- a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightRuntimeCamelContext.java
+++ b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightRuntimeCamelContext.java
@@ -2109,12 +2109,25 @@ public class LightweightRuntimeCamelContext implements ExtendedCamelContext, Cat
throw new UnsupportedOperationException();
}
+ @Override
+ public String addRouteFromTemplate(String routeId, String routeTemplateId, String prefixId, Map<String, Object> parameters)
+ throws Exception {
+ throw new UnsupportedOperationException();
+ }
+
@Override
public String addRouteFromTemplate(String routeId, String routeTemplateId, RouteTemplateContext routeTemplateContext)
throws Exception {
throw new UnsupportedOperationException();
}
+ @Override
+ public String addRouteFromTemplate(
+ String routeId, String routeTemplateId, String prefixId, RouteTemplateContext routeTemplateContext)
+ throws Exception {
+ throw new UnsupportedOperationException();
+ }
+
@Override
public void removeRouteTemplates(String pattern) throws Exception {
throw new UnsupportedOperationException();
diff --git a/core/camel-core-model/src/generated/resources/org/apache/camel/model/templatedRoute.json b/core/camel-core-model/src/generated/resources/org/apache/camel/model/templatedRoute.json
index cfa496c210f..fe5d87f4f42 100644
--- a/core/camel-core-model/src/generated/resources/org/apache/camel/model/templatedRoute.json
+++ b/core/camel-core-model/src/generated/resources/org/apache/camel/model/templatedRoute.json
@@ -14,6 +14,7 @@
"properties": {
"routeTemplateRef": { "kind": "attribute", "displayName": "Route Template Ref", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the id of the route template to use to build the route." },
"routeId": { "kind": "attribute", "displayName": "Route Id", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the id of the route built from the route template." },
+ "prefixId": { "kind": "attribute", "displayName": "Prefix Id", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets a prefix to use when assigning route and node IDs." },
"parameter": { "kind": "element", "displayName": "Parameter", "required": false, "type": "array", "javaType": "java.util.List<org.apache.camel.model.TemplatedRouteParameterDefinition>", "deprecated": false, "autowired": false, "secret": false, "description": "Adds an input parameter of the template to build the route" },
"bean": { "kind": "element", "displayName": "Bean", "required": false, "type": "array", "javaType": "java.util.List<org.apache.camel.model.TemplatedRouteBeanDefinition>", "deprecated": false, "autowired": false, "secret": false, "description": "Adds a local bean as input of the template to build the route" }
}
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/builder/TemplatedRouteBuilder.java b/core/camel-core-model/src/main/java/org/apache/camel/builder/TemplatedRouteBuilder.java
index 9f5bd6a484f..09cd5de0941 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/builder/TemplatedRouteBuilder.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/builder/TemplatedRouteBuilder.java
@@ -36,6 +36,7 @@ public final class TemplatedRouteBuilder {
private final String routeTemplateId;
private final RouteTemplateContext routeTemplateContext;
private String routeId;
+ private String prefixId;
private Consumer<RouteTemplateDefinition> handler;
private Consumer<RouteTemplateContext> configurer;
@@ -67,6 +68,16 @@ public final class TemplatedRouteBuilder {
return this;
}
+ /**
+ * Sets a prefix to use when assigning route and node IDs.
+ *
+ * @param prefixId the prefix id
+ */
+ public TemplatedRouteBuilder prefixId(String prefixId) {
+ this.prefixId = prefixId;
+ return this;
+ }
+
/**
* Adds a parameter the route template will use when creating the route.
*
@@ -165,7 +176,7 @@ public final class TemplatedRouteBuilder {
if (configurer != null) {
routeTemplateContext.setConfigurer(configurer);
}
- return camelContext.addRouteFromTemplate(routeId, routeTemplateId, routeTemplateContext);
+ return camelContext.addRouteFromTemplate(routeId, routeTemplateId, prefixId, routeTemplateContext);
} catch (Exception e) {
throw RuntimeCamelException.wrapRuntimeException(e);
}
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/Model.java b/core/camel-core-model/src/main/java/org/apache/camel/model/Model.java
index ae3528bd3de..a3148f46153 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/Model.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/Model.java
@@ -223,6 +223,21 @@ public interface Model {
*/
String addRouteFromTemplate(String routeId, String routeTemplateId, Map<String, Object> parameters) throws Exception;
+ /**
+ * Adds a new route from a given route template
+ *
+ * @param routeId the id of the new route to add (optional)
+ * @param routeTemplateId the id of the route template (mandatory)
+ * @param prefixId prefix to use when assigning route and node IDs (optional)
+ * @param parameters parameters to use for the route template when creating the new route
+ * @return the id of the route added (for example when an id was auto assigned)
+ * @throws Exception is thrown if error creating and adding the new route
+ */
+ String addRouteFromTemplate(
+ String routeId, String routeTemplateId, String prefixId,
+ Map<String, Object> parameters)
+ throws Exception;
+
/**
* Adds a new route from a given route template
*
@@ -235,6 +250,21 @@ public interface Model {
String addRouteFromTemplate(String routeId, String routeTemplateId, RouteTemplateContext routeTemplateContext)
throws Exception;
+ /**
+ * Adds a new route from a given route template
+ *
+ * @param routeId the id of the new route to add (optional)
+ * @param routeTemplateId the id of the route template (mandatory)
+ * @param prefixId prefix to use when assigning route and node IDs (optional)
+ * @param routeTemplateContext the route template context (mandatory)
+ * @return the id of the route added (for example when an id was auto assigned)
+ * @throws Exception is thrown if error creating and adding the new route
+ */
+ String addRouteFromTemplate(
+ String routeId, String routeTemplateId, String prefixId,
+ RouteTemplateContext routeTemplateContext)
+ throws Exception;
+
/**
* Adds a new route from a given templated route definition
*
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/OptionalIdentifiedDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/OptionalIdentifiedDefinition.java
index f1df499f8b0..7cc89556f6d 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/OptionalIdentifiedDefinition.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/OptionalIdentifiedDefinition.java
@@ -43,8 +43,8 @@ public abstract class OptionalIdentifiedDefinition<T extends OptionalIdentifiedD
private String id;
private Boolean customId;
private DescriptionDefinition description;
- private transient int lineNumber = -1;
- private transient String location;
+ private int lineNumber = -1;
+ private String location;
@Override
public CamelContext getCamelContext() {
@@ -188,10 +188,26 @@ public abstract class OptionalIdentifiedDefinition<T extends OptionalIdentifiedD
* Gets the node id, creating one if not already set.
*/
public String idOrCreate(NodeIdFactory factory) {
+ // prefix is only for nodes in the route (not the route id)
+ String prefix = null;
+ boolean iAmRoute = this instanceof RouteDefinition;
+ boolean allowPrefix = !iAmRoute && this instanceof ProcessorDefinition;
+ if (allowPrefix) {
+ RouteDefinition route = ProcessorDefinitionHelper.getRoute(this);
+ if (route != null) {
+ prefix = route.getNodePrefixId();
+ }
+ }
if (id == null) {
setGeneratedId(factory.createId(this));
}
- return id;
+
+ // return with prefix
+ if (prefix != null) {
+ return prefix + id;
+ } else {
+ return id;
+ }
}
public Boolean getCustomId() {
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/ProcessorDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/ProcessorDefinition.java
index 0f9adf65346..23846c0a94d 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/ProcessorDefinition.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/ProcessorDefinition.java
@@ -865,6 +865,23 @@ public abstract class ProcessorDefinition<Type extends ProcessorDefinition<Type>
return asType();
}
+ /**
+ * Prefix to use for node IDs (both set and auto-assigned IDs)
+ *
+ * @param prefixId the prefix
+ * @return the builder
+ */
+ public Type nodePrefixId(String prefixId) {
+ ProcessorDefinition<?> def = this;
+
+ RouteDefinition route = ProcessorDefinitionHelper.getRoute(def);
+ if (route != null) {
+ route.setNodePrefixId(prefixId);
+ }
+
+ return asType();
+ }
+
/**
* Disables this EIP from the route during build time. Once an EIP has been disabled then it cannot be enabled later
* at runtime.
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteDefinition.java
index 9f591c6205a..48fe5496bef 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteDefinition.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteDefinition.java
@@ -66,6 +66,7 @@ public class RouteDefinition extends OutputDefinition<RouteDefinition>
private String routeConfigurationId;
private transient Set<String> appliedRouteConfigurationIds;
private String group;
+ private String nodePrefixId;
private String streamCache;
private String trace;
private String messageHistory;
@@ -280,6 +281,18 @@ public class RouteDefinition extends OutputDefinition<RouteDefinition>
return this;
}
+ /**
+ * Prefix to use for node IDs (both set and auto-assigned IDs)
+ *
+ * @param prefixId the prefix
+ * @return the builder
+ */
+ @Override
+ public RouteDefinition nodePrefixId(String prefixId) {
+ setNodePrefixId(prefixId);
+ return this;
+ }
+
/**
* Disable stream caching for this route.
*
@@ -855,6 +868,22 @@ public class RouteDefinition extends OutputDefinition<RouteDefinition>
this.group = group;
}
+ /**
+ * Prefix to use for route and node IDs (also IDs that has been explicit set to a value)
+ */
+ public String getNodePrefixId() {
+ return nodePrefixId;
+ }
+
+ /**
+ * Prefix to use for route and node IDs (also IDs that has been explicit set to a value)
+ */
+ @XmlAttribute
+ @Metadata(label = "advanced")
+ public void setNodePrefixId(String nodePrefixId) {
+ this.nodePrefixId = nodePrefixId;
+ }
+
/**
* Whether stream caching is enabled on this route.
*/
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteDefinitionHelper.java b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteDefinitionHelper.java
index 0e27dc6af8a..2b07b5bb86a 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteDefinitionHelper.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteDefinitionHelper.java
@@ -245,6 +245,18 @@ public final class RouteDefinitionHelper {
* @return <tt>null</tt> if no duplicate id's detected, otherwise the first found duplicate id is returned.
*/
public static String validateUniqueIds(RouteDefinition target, List<RouteDefinition> routes) {
+ return validateUniqueIds(target, routes, null);
+ }
+
+ /**
+ * Validates that the target route has no duplicate id's from any of the existing routes.
+ *
+ * @param target the target route
+ * @param routes the existing routes
+ * @param prefixId optional prefix to use in duplicate id detection
+ * @return <tt>null</tt> if no duplicate id's detected, otherwise the first found duplicate id is returned.
+ */
+ public static String validateUniqueIds(RouteDefinition target, List<RouteDefinition> routes, String prefixId) {
Set<String> routesIds = new LinkedHashSet<>();
// gather all ids for the existing route, but only include custom ids,
// and no abstract ids
@@ -267,6 +279,9 @@ public final class RouteDefinitionHelper {
// now check for clash with the target route
for (String id : targetIds) {
+ if (prefixId != null) {
+ id = prefixId + id;
+ }
if (routesIds.contains(id)) {
return id;
}
@@ -739,6 +754,29 @@ public final class RouteDefinitionHelper {
}
}
+ /**
+ * For all custom assigned ids, then to avoid duplicate ids when creating new routes from route templates, then the
+ * custom assigned ids, must be prefixed.
+ *
+ * @param context the camel context
+ * @param prefix the prefix to set on custom assigned id
+ * @param processor the node
+ */
+ public static void prefixCustomAssignIds(CamelContext context, final String prefix, final ProcessorDefinition processor) {
+ if (processor.hasCustomIdAssigned()) {
+ String originalId = processor.getId();
+ String newId = prefix + originalId;
+ processor.setId(newId);
+ }
+
+ List<ProcessorDefinition<?>> children = processor.getOutputs();
+ if (children != null && !children.isEmpty()) {
+ for (ProcessorDefinition child : children) {
+ prefixCustomAssignIds(context, prefix, child);
+ }
+ }
+ }
+
public static String getRouteMessage(String route) {
// cut the route after 60 chars, so it won't be too big in the message
// users just need to be able to identify the route, so they know where to look
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/TemplatedRouteDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/TemplatedRouteDefinition.java
index 98da50a8c9b..5db5ae8942b 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/TemplatedRouteDefinition.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/TemplatedRouteDefinition.java
@@ -50,6 +50,8 @@ public class TemplatedRouteDefinition implements CamelContextAware {
private String routeTemplateRef;
@XmlAttribute
private String routeId;
+ @XmlAttribute
+ private String prefixId;
@XmlElement(name = "parameter")
@Metadata(description = "Adds an input parameter of the template to build the route")
private List<TemplatedRouteParameterDefinition> parameters;
@@ -89,6 +91,14 @@ public class TemplatedRouteDefinition implements CamelContextAware {
this.routeId = routeId;
}
+ public String getPrefixId() {
+ return prefixId;
+ }
+
+ public void setPrefixId(String prefixId) {
+ this.prefixId = prefixId;
+ }
+
@Override
public CamelContext getCamelContext() {
return camelContext;
@@ -260,6 +270,16 @@ public class TemplatedRouteDefinition implements CamelContextAware {
return def;
}
+ /**
+ * Sets a prefix to use when assigning route and node IDs.
+ *
+ * @param id the prefix id
+ */
+ public TemplatedRouteDefinition prefixId(String id) {
+ setPrefixId(id);
+ return this;
+ }
+
/**
* Sets the id of the route built from the route template.
*
diff --git a/core/camel-core/src/test/java/org/apache/camel/builder/RouteTemplatePrefixIdTest.java b/core/camel-core/src/test/java/org/apache/camel/builder/RouteTemplatePrefixIdTest.java
new file mode 100644
index 00000000000..eadba72450a
--- /dev/null
+++ b/core/camel-core/src/test/java/org/apache/camel/builder/RouteTemplatePrefixIdTest.java
@@ -0,0 +1,194 @@
+/*
+ * 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.HashMap;
+import java.util.Map;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.Route;
+import org.apache.camel.model.RouteTemplateDefinition;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+public class RouteTemplatePrefixIdTest extends ContextTestSupport {
+
+ // TODO: docs
+ // TODO: <xml> tests
+ // TODO: regen
+
+ @Test
+ public void testDefineRouteTemplate() throws Exception {
+ assertEquals(1, context.getRouteTemplateDefinitions().size());
+
+ RouteTemplateDefinition routeTemplate = context.getRouteTemplateDefinition("myTemplate");
+ assertEquals("foo", routeTemplate.getTemplateParameters().get(0).getName());
+ assertEquals("bar", routeTemplate.getTemplateParameters().get(1).getName());
+ }
+
+ @Test
+ public void testCreateRouteFromRouteTemplate() throws Exception {
+ assertEquals(1, context.getRouteTemplateDefinitions().size());
+
+ RouteTemplateDefinition routeTemplate = context.getRouteTemplateDefinition("myTemplate");
+ assertEquals("foo", routeTemplate.getTemplateParameters().get(0).getName());
+ assertEquals("bar", routeTemplate.getTemplateParameters().get(1).getName());
+
+ getMockEndpoint("mock:cheese").expectedBodiesReceived("Hello Cheese");
+ getMockEndpoint("mock:cake").expectedBodiesReceived("Hello Cake");
+
+ Map<String, Object> parameters = new HashMap<>();
+ parameters.put("foo", "one");
+ parameters.put("bar", "cheese");
+ context.addRouteFromTemplate("first", "myTemplate", "aaa", parameters);
+
+ parameters.put("foo", "two");
+ parameters.put("bar", "cake");
+ context.addRouteFromTemplate("second", "myTemplate", "bbb", parameters);
+
+ assertEquals(2, context.getRouteDefinitions().size());
+ assertEquals(2, context.getRoutes().size());
+ assertEquals("Started", context.getRouteController().getRouteStatus("first").name());
+ assertEquals("Started", context.getRouteController().getRouteStatus("second").name());
+ assertEquals("true", context.getRoute("first").getProperties().get(Route.TEMPLATE_PROPERTY));
+ assertEquals("true", context.getRoute("second").getProperties().get(Route.TEMPLATE_PROPERTY));
+
+ template.sendBody("direct:one", "Hello Cheese");
+ template.sendBody("direct:two", "Hello Cake");
+
+ assertMockEndpointsSatisfied();
+ }
+
+ @Test
+ public void testCreateRouteFromRouteTemplateFluent() throws Exception {
+ assertEquals(1, context.getRouteTemplateDefinitions().size());
+
+ RouteTemplateDefinition routeTemplate = context.getRouteTemplateDefinition("myTemplate");
+ assertEquals("foo", routeTemplate.getTemplateParameters().get(0).getName());
+ assertEquals("bar", routeTemplate.getTemplateParameters().get(1).getName());
+
+ getMockEndpoint("mock:cheese").expectedBodiesReceived("Hello Cheese");
+ getMockEndpoint("mock:cake").expectedBodiesReceived("Hello Cake");
+
+ TemplatedRouteBuilder.builder(context, "myTemplate")
+ .routeId("first")
+ .prefixId("aaa")
+ .parameter("foo", "one")
+ .parameter("bar", "cheese")
+ .add();
+
+ TemplatedRouteBuilder.builder(context, "myTemplate")
+ .routeId("second")
+ .prefixId("bbb")
+ .parameter("foo", "two")
+ .parameter("bar", "cake")
+ .add();
+
+ assertEquals(2, context.getRouteDefinitions().size());
+ assertEquals(2, context.getRoutes().size());
+ assertEquals("Started", context.getRouteController().getRouteStatus("first").name());
+ assertEquals("Started", context.getRouteController().getRouteStatus("second").name());
+ assertEquals("true", context.getRoute("first").getProperties().get(Route.TEMPLATE_PROPERTY));
+ assertEquals("true", context.getRoute("second").getProperties().get(Route.TEMPLATE_PROPERTY));
+
+ template.sendBody("direct:one", "Hello Cheese");
+ template.sendBody("direct:two", "Hello Cake");
+
+ assertMockEndpointsSatisfied();
+ }
+
+ @Test
+ public void testCreateRouteFromRouteTemplateAutoAssignedRouteId() throws Exception {
+ assertEquals(1, context.getRouteTemplateDefinitions().size());
+
+ RouteTemplateDefinition routeTemplate = context.getRouteTemplateDefinition("myTemplate");
+ assertEquals("foo", routeTemplate.getTemplateParameters().get(0).getName());
+ assertEquals("bar", routeTemplate.getTemplateParameters().get(1).getName());
+
+ getMockEndpoint("mock:cheese").expectedBodiesReceived("Hello Cheese");
+
+ Map<String, Object> parameters = new HashMap<>();
+ parameters.put("foo", "one");
+ parameters.put("bar", "cheese");
+ String routeId = context.addRouteFromTemplate(null, "myTemplate", "aaa", parameters);
+
+ assertNotNull(routeId);
+ assertEquals(1, context.getRouteDefinitions().size());
+ assertEquals(1, context.getRoutes().size());
+ assertEquals("Started", context.getRouteController().getRouteStatus(routeId).name());
+ assertEquals("true", context.getRoute(routeId).getProperties().get(Route.TEMPLATE_PROPERTY));
+
+ template.sendBody("direct:one", "Hello Cheese");
+
+ assertMockEndpointsSatisfied();
+ }
+
+ @Test
+ public void testCreateRouteFromRouteTemplateAutoAssignedRouteIdClash() throws Exception {
+ context.addRoutes(new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ // use a route id that can clash with auto assigned
+ from("direct:hello").to("mock:hello").routeId("route1");
+ }
+ });
+
+ assertEquals(1, context.getRouteDefinitions().size());
+ assertEquals(1, context.getRouteTemplateDefinitions().size());
+
+ RouteTemplateDefinition routeTemplate = context.getRouteTemplateDefinition("myTemplate");
+ assertEquals("foo", routeTemplate.getTemplateParameters().get(0).getName());
+ assertEquals("bar", routeTemplate.getTemplateParameters().get(1).getName());
+
+ getMockEndpoint("mock:cheese").expectedBodiesReceived("Hello Cheese");
+
+ Map<String, Object> parameters = new HashMap<>();
+ parameters.put("foo", "one");
+ parameters.put("bar", "cheese");
+ String routeId = context.addRouteFromTemplate(null, "myTemplate", "aaa", parameters);
+
+ assertNotNull(routeId);
+ assertNotEquals("route1", routeId, "Should not be named route1");
+ assertEquals(2, context.getRouteDefinitions().size());
+ assertEquals(2, context.getRoutes().size());
+ assertEquals("Started", context.getRouteController().getRouteStatus(routeId).name());
+ assertEquals("true", context.getRoute(routeId).getProperties().get(Route.TEMPLATE_PROPERTY));
+
+ template.sendBody("direct:one", "Hello Cheese");
+
+ assertMockEndpointsSatisfied();
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ routeTemplate("myTemplate").templateParameter("foo").templateParameter("bar")
+ .from("direct:{{foo}}")
+ .choice()
+ .when(header("foo"))
+ .log("${body}").id("myLog")
+ .otherwise()
+ .to("mock:{{bar}}").id("end");
+ }
+ };
+ }
+}
diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/RouteNodePrefixIdDuplicateTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/RouteNodePrefixIdDuplicateTest.java
new file mode 100644
index 00000000000..28796d46c7d
--- /dev/null
+++ b/core/camel-core/src/test/java/org/apache/camel/processor/RouteNodePrefixIdDuplicateTest.java
@@ -0,0 +1,58 @@
+/*
+ * 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.processor;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.builder.RouteBuilder;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class RouteNodePrefixIdDuplicateTest extends ContextTestSupport {
+
+ @Test
+ public void testRoutePrefixId() throws Exception {
+ Assertions.assertEquals(2, context.getRoutes().size());
+
+ // ID should be prefixed
+ SendProcessor send = context.getProcessor("myMock", SendProcessor.class);
+ Assertions.assertNull(send);
+ send = context.getProcessor("aaamyMock", SendProcessor.class);
+ Assertions.assertNotNull(send);
+ send = context.getProcessor("bbbmyMock", SendProcessor.class);
+ Assertions.assertNotNull(send);
+
+ // all nodes should include prefix
+ Assertions.assertEquals(2, context.getRoute("foo").filter("aaa*").size());
+ Assertions.assertEquals(2, context.getRoute("bar").filter("bbb*").size());
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ from("direct:foo").routeId("foo").nodePrefixId("aaa")
+ .to("mock:foo").id("myMock")
+ .to("seda:foo");
+
+ from("direct:bar").nodePrefixId("bbb").routeId("bar")
+ .to("mock:bar").id("myMock")
+ .to("seda:bar");
+ }
+ };
+ }
+}
diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/RouteNodePrefixIdTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/RouteNodePrefixIdTest.java
new file mode 100644
index 00000000000..61e8c5216a3
--- /dev/null
+++ b/core/camel-core/src/test/java/org/apache/camel/processor/RouteNodePrefixIdTest.java
@@ -0,0 +1,70 @@
+/*
+ * 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.processor;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.builder.RouteBuilder;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class RouteNodePrefixIdTest extends ContextTestSupport {
+
+ @Test
+ public void testRoutePrefixId() throws Exception {
+ Assertions.assertEquals(3, context.getRoutes().size());
+
+ // ID should be prefixed
+ SendProcessor send = context.getProcessor("aaamyFoo", SendProcessor.class);
+ Assertions.assertNotNull(send);
+ send = context.getProcessor("bbbmyBar", SendProcessor.class);
+ Assertions.assertNotNull(send);
+ send = context.getProcessor("cccmyCheese", SendProcessor.class);
+ Assertions.assertNotNull(send);
+
+ // all nodes should include prefix
+ Assertions.assertEquals(2, context.getRoute("foo").filter("aaa*").size());
+ Assertions.assertEquals(2, context.getRoute("bar").filter("bbb*").size());
+ Assertions.assertEquals(3, context.getRoutes().get(2).filter("ccc*").size());
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ from("direct:foo").routeId("foo").nodePrefixId("aaa")
+ .to("mock:foo").id("myFoo")
+ .to("seda:foo");
+
+ from("direct:bar").nodePrefixId("bbb").routeId("bar")
+ .to("mock:bar").id("myBar")
+ .to("seda:bar");
+
+ from("direct:cheese")
+ .nodePrefixId("ccc")
+ .choice()
+ .when(header("cheese"))
+ .to("mock:cheese").id("myCheese")
+ .otherwise()
+ .to("mock:gauda")
+ .end();
+ }
+ };
+ }
+}
diff --git a/core/camel-main/src/test/java/org/apache/camel/main/MainTemplatedRoutePrefixIdTest.java b/core/camel-main/src/test/java/org/apache/camel/main/MainTemplatedRoutePrefixIdTest.java
new file mode 100644
index 00000000000..1d5e9e8686b
--- /dev/null
+++ b/core/camel-main/src/test/java/org/apache/camel/main/MainTemplatedRoutePrefixIdTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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.builder.RouteBuilder;
+import org.apache.camel.processor.LogProcessor;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class MainTemplatedRoutePrefixIdTest {
+
+ @Test
+ void testMain() throws Exception {
+ Main main = new Main();
+ main.configure().addRoutesBuilder(new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ routeTemplate("myTemplate")
+ .templateParameter("foo")
+ .templateParameter("bar")
+ .from("direct:{{foo}}")
+ .choice()
+ .when(header("foo"))
+ .log("${body}").id("myLog")
+ .otherwise()
+ .to("mock:{{bar}}").id("end");
+
+ templatedRoute("myTemplate")
+ .routeId("my-route")
+ .prefixId("aaa")
+ .parameter("foo", "fooVal")
+ .parameter("bar", "barVal");
+
+ templatedRoute("myTemplate")
+ .routeId("my-route2")
+ .prefixId("bbb")
+ .parameter("foo", "fooVal2")
+ .parameter("bar", "barVal2");
+ }
+ });
+
+ main.start();
+
+ CamelContext context = main.getCamelContext();
+ assertEquals(2, context.getRoutes().size());
+
+ // ID should be prefixed
+ LogProcessor log = context.getProcessor("aaamyLog", LogProcessor.class);
+ Assertions.assertNotNull(log);
+ log = context.getProcessor("bbbmyLog", LogProcessor.class);
+ Assertions.assertNotNull(log);
+
+ // all nodes should include prefix
+ Assertions.assertEquals(3, context.getRoute("my-route").filter("aaa*").size());
+ Assertions.assertEquals(3, context.getRoute("my-route2").filter("bbb*").size());
+
+ main.stop();
+ }
+
+}
diff --git a/core/camel-support/src/main/java/org/apache/camel/support/LocalBeanRegistry.java b/core/camel-support/src/main/java/org/apache/camel/support/LocalBeanRegistry.java
index 08426c6ca9f..d26845f611a 100644
--- a/core/camel-support/src/main/java/org/apache/camel/support/LocalBeanRegistry.java
+++ b/core/camel-support/src/main/java/org/apache/camel/support/LocalBeanRegistry.java
@@ -48,9 +48,11 @@ public final class LocalBeanRegistry extends SupplierRegistry {
* registry or endpoint registry in Camel. Then there is a check that validates for clashes and then re-assign key
* names.
*
- * @param oldKey the old key name
- * @param newKey the new key name
+ * @param oldKey the old key name
+ * @param newKey the new key name
+ * @deprecated not in use
*/
+ @Deprecated
public void swapKey(String oldKey, String newKey) {
Map<Class<?>, Object> value = remove(oldKey);
if (value != null) {
diff --git a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
index f4aaa921674..297e9f235fe 100644
--- a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
+++ b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
@@ -1043,6 +1043,7 @@ public class ModelParser extends BaseParser {
case "group": def.setGroup(val); break;
case "logMask": def.setLogMask(val); break;
case "messageHistory": def.setMessageHistory(val); break;
+ case "nodePrefixId": def.setNodePrefixId(val); break;
case "precondition": def.setPrecondition(val); break;
case "routeConfigurationId": def.setRouteConfigurationId(val); break;
case "routePolicyRef": def.setRoutePolicyRef(val); break;
@@ -1363,6 +1364,7 @@ public class ModelParser extends BaseParser {
protected TemplatedRouteDefinition doParseTemplatedRouteDefinition() throws IOException, XmlPullParserException {
return doParse(new TemplatedRouteDefinition(), (def, key, val) -> {
switch (key) {
+ case "prefixId": def.setPrefixId(val); break;
case "routeId": def.setRouteId(val); break;
case "routeTemplateRef": def.setRouteTemplateRef(val); break;
default: return false;