This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new 9e7cb82f5c4 CAMEL-22420: camel-core - Detect duplicate processor ids
within same route (#19264)
9e7cb82f5c4 is described below
commit 9e7cb82f5c4d029c4be9710351a03179055ee177
Author: Claus Ibsen <[email protected]>
AuthorDate: Sat Sep 20 12:05:42 2025 +0200
CAMEL-22420: camel-core - Detect duplicate processor ids within same route
(#19264)
---
.../camel/model/ProcessorDefinitionHelper.java | 12 +++++------
.../apache/camel/model/RouteDefinitionHelper.java | 22 ++++++++++++++------
.../camel/management/ManagedDuplicateIdTest.java | 24 ++++++++++++++++++++++
3 files changed, 45 insertions(+), 13 deletions(-)
diff --git
a/core/camel-core-model/src/main/java/org/apache/camel/model/ProcessorDefinitionHelper.java
b/core/camel-core-model/src/main/java/org/apache/camel/model/ProcessorDefinitionHelper.java
index 1dd53f99079..1372486a803 100644
---
a/core/camel-core-model/src/main/java/org/apache/camel/model/ProcessorDefinitionHelper.java
+++
b/core/camel-core-model/src/main/java/org/apache/camel/model/ProcessorDefinitionHelper.java
@@ -18,9 +18,7 @@ package org.apache.camel.model;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.LinkedHashSet;
import java.util.List;
-import java.util.Set;
import org.apache.camel.CamelContext;
import org.apache.camel.NamedNode;
@@ -180,15 +178,15 @@ public final class ProcessorDefinitionHelper {
* Traverses the node, including its children (recursive), and gathers all
the node ids.
*
* @param node the target node
- * @param set set to store ids, if <tt>null</tt> a new set
will be created
+ * @param set list to store ids, if <tt>null</tt> a new list
will be created
* @param onlyCustomId whether to only store custom assigned ids (ie.
* {@link
org.apache.camel.model.OptionalIdentifiedDefinition#hasCustomIdAssigned()}
* @param includeAbstract whether to include abstract nodes (ie.
* {@link
org.apache.camel.model.ProcessorDefinition#isAbstract()}
- * @return the set with the found ids.
+ * @return the list with the found ids.
*/
- public static Set<String> gatherAllNodeIds(
- ProcessorDefinition<?> node, Set<String> set, boolean
onlyCustomId, boolean includeAbstract) {
+ public static List<String> gatherAllNodeIds(
+ ProcessorDefinition<?> node, List<String> set, boolean
onlyCustomId, boolean includeAbstract) {
if (node == null) {
return set;
}
@@ -199,7 +197,7 @@ public final class ProcessorDefinitionHelper {
}
if (set == null) {
- set = new LinkedHashSet<>();
+ set = new ArrayList<>();
}
// add ourselves
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 da1748462db..8645a0d35db 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
@@ -22,11 +22,14 @@ import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
+import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
+import java.util.function.Function;
import java.util.function.Predicate;
+import java.util.stream.Collectors;
import org.apache.camel.CamelContext;
import org.apache.camel.ErrorHandlerFactory;
@@ -260,11 +263,9 @@ 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, String prefixId) {
- Set<String> routesIds = new LinkedHashSet<>();
- // gather all ids for the existing route, but only include custom ids,
- // and no abstract ids
- // as abstract nodes is cross-cutting functionality such as
interceptors
- // etc
+ List<String> routesIds = new ArrayList<>();
+ // gather all ids for the existing route, but only include custom ids,
and no abstract ids
+ // as abstract nodes is cross-cutting functionality such as
interceptors etc
for (RouteDefinition route : routes) {
// skip target route as we gather ids in a separate set
if (route == target) {
@@ -275,8 +276,17 @@ public final class RouteDefinitionHelper {
// gather all ids for the target route, but only include custom ids,
and
// no abstract ids as abstract nodes is cross-cutting functionality
such as interceptors etc
- Set<String> targetIds = new LinkedHashSet<>();
+ List<String> targetIds = new ArrayList<>();
ProcessorDefinitionHelper.gatherAllNodeIds(target, targetIds, true,
false);
+ // are there any duplicates processor ids in the target route
+ List<String> duplicates =
targetIds.stream().collect(Collectors.groupingBy(Function.identity()))
+ .entrySet().stream()
+ .filter(e -> e.getValue().size() > 1)
+ .map(Map.Entry::getKey)
+ .toList();
+ if (!duplicates.isEmpty()) {
+ return duplicates.get(0);
+ }
// now check for clash with the target route
for (String id : targetIds) {
diff --git
a/core/camel-management/src/test/java/org/apache/camel/management/ManagedDuplicateIdTest.java
b/core/camel-management/src/test/java/org/apache/camel/management/ManagedDuplicateIdTest.java
index 22dc06931eb..f5b4a847724 100644
---
a/core/camel-management/src/test/java/org/apache/camel/management/ManagedDuplicateIdTest.java
+++
b/core/camel-management/src/test/java/org/apache/camel/management/ManagedDuplicateIdTest.java
@@ -57,6 +57,30 @@ public class ManagedDuplicateIdTest extends
ManagementTestSupport {
}
}
+ @Test
+ public void testDuplicateIdSingleRoute() throws Exception {
+ context.addRoutes(new RouteBuilder() {
+ @Override
+ public void configure() {
+ from("direct:foo").routeId("foo")
+ .to("log:line").id("clash")
+ .to("log:foo").id("cheese")
+ .split(body()).id("mysplit")
+ .to("log:line").id("clash")
+ .end()
+ .to("mock:foo");
+ }
+ });
+ try {
+ context.start();
+ fail("Should fail");
+ } catch (Exception e) {
+ assertEquals(
+ "Failed to start route: foo because: Duplicate id
detected: clash. Please correct ids to be unique among all your routes.",
+ e.getMessage());
+ }
+ }
+
@Override
public boolean isUseRouteBuilder() {
return false;