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 3dcc4cfcaa57 CAMEL-25064: camel-management - EIP and service MBeans: 
fix bugs found in a deep review (#26958)
3dcc4cfcaa57 is described below

commit 3dcc4cfcaa571ba7e5370e360621a19f9d36a7ca
Author: Claus Ibsen <[email protected]>
AuthorDate: Mon Sep 28 09:23:54 2026 +0200

    CAMEL-25064: camel-management - EIP and service MBeans: fix bugs found in a 
deep review (#26958)
    
    - tabular data keyed by a non-unique value failed with 
KeyAlreadyExistsException: choice and doTry
      extendedInformation, listTasks (new index item), exchange factory 
listStatistics (url and routeId),
      endpoint utilization and listEndpoints for endpoints that only differ in 
a (masked) secret
    - listEndpoints reports static/dynamic by the real uri (not the masked)
    - choice extendedInformation pairs the right predicate when a when is 
disabled
    - ForceCompletionOnStop of the aggregate MBean returns the right option
    - the endpoint utilization tabular data of 8 EIP MBeans is built by one 
helper
    
    Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
    Signed-off-by: Claus Ibsen <[email protected]>
---
 .../processor/aggregate/AggregateProcessor.java    |   4 +
 .../api/management/mbean/CamelOpenMBeanTypes.java  |  33 ++--
 .../mbean/EndpointUtilizationHelper.java           |  63 +++++++
 .../mbean/ManagedAggregateProcessor.java           |   2 +-
 .../camel/management/mbean/ManagedChoice.java      |  19 +-
 .../camel/management/mbean/ManagedDoTry.java       |   4 +-
 .../management/mbean/ManagedDynamicRouter.java     |  31 +---
 .../management/mbean/ManagedEndpointRegistry.java  |  13 +-
 .../camel/management/mbean/ManagedEnricher.java    |  31 +---
 .../apache/camel/management/mbean/ManagedPoll.java |  31 +---
 .../management/mbean/ManagedPollEnricher.java      |  31 +---
 .../management/mbean/ManagedRecipientList.java     |  31 +---
 .../camel/management/mbean/ManagedRoutingSlip.java |  31 +---
 .../mbean/ManagedSendDynamicProcessor.java         |  31 +---
 .../mbean/ManagedTaskManagerRegistry.java          |   8 +-
 .../management/mbean/ManagedWireTapProcessor.java  |  31 +---
 .../ManagedTabularDataEdgeCasesTest.java           | 201 +++++++++++++++++++++
 .../ROOT/pages/camel-4x-upgrade-guide-4_23.adoc    |   7 +
 18 files changed, 331 insertions(+), 271 deletions(-)

diff --git 
a/core/camel-core-processor/src/main/java/org/apache/camel/processor/aggregate/AggregateProcessor.java
 
b/core/camel-core-processor/src/main/java/org/apache/camel/processor/aggregate/AggregateProcessor.java
index aa569e1a4a5a..be77dbbfb0b3 100644
--- 
a/core/camel-core-processor/src/main/java/org/apache/camel/processor/aggregate/AggregateProcessor.java
+++ 
b/core/camel-core-processor/src/main/java/org/apache/camel/processor/aggregate/AggregateProcessor.java
@@ -1202,6 +1202,10 @@ public class AggregateProcessor extends 
BaseProcessorSupport
         this.discardOnAggregationFailure = discardOnAggregationFailure;
     }
 
+    public boolean isForceCompletionOnStop() {
+        return forceCompletionOnStop;
+    }
+
     public void setForceCompletionOnStop(boolean forceCompletionOnStop) {
         this.forceCompletionOnStop = forceCompletionOnStop;
     }
diff --git 
a/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/CamelOpenMBeanTypes.java
 
b/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/CamelOpenMBeanTypes.java
index 5f5fc6a486be..9c1b3eb77d63 100644
--- 
a/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/CamelOpenMBeanTypes.java
+++ 
b/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/CamelOpenMBeanTypes.java
@@ -85,7 +85,8 @@ public final class CamelOpenMBeanTypes {
 
     public static TabularType listExchangeFactoryTabularType() throws 
OpenDataException {
         CompositeType ct = listExchangeFactoryCompositeType();
-        return new TabularType("listExchangeFactory", "Lists all the exchange 
factories", ct, new String[] { "url" });
+        return new TabularType(
+                "listExchangeFactory", "Lists all the exchange factories", ct, 
new String[] { "url", "routeId" });
     }
 
     public static CompositeType listExchangeFactoryCompositeType() throws 
OpenDataException {
@@ -193,28 +194,29 @@ public final class CamelOpenMBeanTypes {
 
     public static TabularType choiceTabularType() throws OpenDataException {
         CompositeType ct = choiceCompositeType();
-        return new TabularType("choice", "Choice statistics", ct, new String[] 
{ "predicate" });
+        return new TabularType("choice", "Choice statistics", ct, new String[] 
{ "index" });
     }
 
     public static CompositeType choiceCompositeType() throws OpenDataException 
{
         return new CompositeType(
                 "predicates", "Predicates",
-                new String[] { "predicate", "language", "matches" },
-                new String[] { "Predicate", "Language", "Matches" },
-                new OpenType[] { SimpleType.STRING, SimpleType.STRING, 
SimpleType.LONG });
+                new String[] { "index", "predicate", "language", "matches" },
+                new String[] { "Index", "Predicate", "Language", "Matches" },
+                new OpenType[] { SimpleType.INTEGER, SimpleType.STRING, 
SimpleType.STRING, SimpleType.LONG });
     }
 
     public static TabularType doTryTabularType() throws OpenDataException {
         CompositeType ct = doTryCompositeType();
-        return new TabularType("doTry", "doTry statistics", ct, new String[] { 
"exception" });
+        return new TabularType("doTry", "doTry statistics", ct, new String[] { 
"index" });
     }
 
     public static CompositeType doTryCompositeType() throws OpenDataException {
         return new CompositeType(
                 "exceptions", "Exception types",
-                new String[] { "exception", "predicate", "language", "matches" 
},
-                new String[] { "Exception", "Predicate", "Language", "Matches" 
},
-                new OpenType[] { SimpleType.STRING, SimpleType.STRING, 
SimpleType.STRING, SimpleType.LONG });
+                new String[] { "index", "exception", "predicate", "language", 
"matches" },
+                new String[] { "Index", "Exception", "Predicate", "Language", 
"Matches" },
+                new OpenType[] {
+                        SimpleType.INTEGER, SimpleType.STRING, 
SimpleType.STRING, SimpleType.STRING, SimpleType.LONG });
     }
 
     public static TabularType loadbalancerExceptionsTabularType() throws 
OpenDataException {
@@ -362,20 +364,21 @@ public final class CamelOpenMBeanTypes {
         CompositeType ct = listInternalTaskCompositeType();
         return new TabularType(
                 "listTask", "Lists all the internal tasks", ct,
-                new String[] { "name" });
+                new String[] { "index" });
     }
 
     public static CompositeType listInternalTaskCompositeType() throws 
OpenDataException {
         return new CompositeType(
                 "tasks", "Tasks",
                 new String[] {
-                        "name", "kind", "status", "attempts", "delay", 
"elapsed", "firstTime", "lastTime", "nextTime",
-                        "failure" },
+                        "index", "name", "kind", "status", "attempts", 
"delay", "elapsed", "firstTime", "lastTime",
+                        "nextTime", "failure" },
                 new String[] {
-                        "Name", "Kind", "Status", "Attempts", "Delay", 
"Elapsed", "FirstTime", "LastTime", "NextTime",
-                        "Failure" },
+                        "Index", "Name", "Kind", "Status", "Attempts", 
"Delay", "Elapsed", "FirstTime", "LastTime",
+                        "NextTime", "Failure" },
                 new OpenType[] {
-                        SimpleType.STRING, SimpleType.STRING, 
SimpleType.STRING, SimpleType.LONG, SimpleType.LONG,
+                        SimpleType.INTEGER, SimpleType.STRING, 
SimpleType.STRING, SimpleType.STRING, SimpleType.LONG,
+                        SimpleType.LONG,
                         SimpleType.LONG, SimpleType.LONG, SimpleType.LONG, 
SimpleType.LONG, SimpleType.STRING });
     }
 
diff --git 
a/core/camel-management/src/main/java/org/apache/camel/management/mbean/EndpointUtilizationHelper.java
 
b/core/camel-management/src/main/java/org/apache/camel/management/mbean/EndpointUtilizationHelper.java
new file mode 100644
index 000000000000..5e18c626f766
--- /dev/null
+++ 
b/core/camel-management/src/main/java/org/apache/camel/management/mbean/EndpointUtilizationHelper.java
@@ -0,0 +1,63 @@
+/*
+ * 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.management.mbean;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenDataException;
+import javax.management.openmbean.TabularData;
+import javax.management.openmbean.TabularDataSupport;
+
+import org.apache.camel.api.management.mbean.CamelOpenMBeanTypes;
+import org.apache.camel.spi.EndpointUtilizationStatistics;
+import org.apache.camel.util.URISupport;
+
+/**
+ * The endpoint utilization statistics of an EIP (such as toD) as tabular data.
+ */
+final class EndpointUtilizationHelper {
+
+    private EndpointUtilizationHelper() {
+    }
+
+    static TabularData toTabularData(EndpointUtilizationStatistics stats, 
boolean sanitize) throws OpenDataException {
+        TabularData answer = new 
TabularDataSupport(CamelOpenMBeanTypes.endpointsUtilizationTabularType());
+        if (stats != null) {
+            // endpoints that only differ in a secret are the same url when 
sanitized, so their hits are merged
+            Map<String, Long> hitsPerUrl = new LinkedHashMap<>();
+            for (Map.Entry<String, Long> entry : 
stats.getStatistics().entrySet()) {
+                String url = entry.getKey();
+                if (sanitize) {
+                    url = URISupport.sanitizeUri(url);
+                }
+                long hits = entry.getValue() != null ? entry.getValue() : 0L;
+                hitsPerUrl.merge(url, hits, Long::sum);
+            }
+            CompositeType ct = 
CamelOpenMBeanTypes.endpointsUtilizationCompositeType();
+            for (Map.Entry<String, Long> entry : hitsPerUrl.entrySet()) {
+                CompositeData data = new CompositeDataSupport(
+                        ct, new String[] { "url", "hits" }, new Object[] { 
entry.getKey(), entry.getValue() });
+                answer.put(data);
+            }
+        }
+        return answer;
+    }
+}
diff --git 
a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedAggregateProcessor.java
 
b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedAggregateProcessor.java
index 5b196dad0429..dddf5d16c079 100644
--- 
a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedAggregateProcessor.java
+++ 
b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedAggregateProcessor.java
@@ -175,7 +175,7 @@ public class ManagedAggregateProcessor extends 
ManagedProcessor implements Manag
 
     @Override
     public boolean isForceCompletionOnStop() {
-        return getProcessor().isCompletionFromBatchConsumer();
+        return getProcessor().isForceCompletionOnStop();
     }
 
     @Override
diff --git 
a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedChoice.java
 
b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedChoice.java
index 29d93aa73f0e..f5f50529b89c 100644
--- 
a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedChoice.java
+++ 
b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedChoice.java
@@ -34,6 +34,7 @@ import org.apache.camel.model.ProcessorDefinition;
 import org.apache.camel.model.WhenDefinition;
 import org.apache.camel.processor.ChoiceProcessor;
 import org.apache.camel.processor.FilterProcessor;
+import org.apache.camel.reifier.ProcessorReifier;
 
 @ManagedResource(description = "Managed Choice")
 public class ManagedChoice extends ManagedProcessor implements 
ManagedChoiceMBean {
@@ -68,10 +69,13 @@ public class ManagedChoice extends ManagedProcessor 
implements ManagedChoiceMBea
         try {
             TabularData answer = new 
TabularDataSupport(CamelOpenMBeanTypes.choiceTabularType());
 
-            List<WhenDefinition> whens = getDefinition().getWhenClauses();
+            // there is a filter for each when that is not disabled
+            List<WhenDefinition> whens = 
getDefinition().getWhenClauses().stream()
+                    .filter(w -> !ProcessorReifier.isDisabled(getContext(), w))
+                    .toList();
             List<FilterProcessor> filters = getProcessor().getFilters();
 
-            for (int i = 0; i < filters.size(); i++) {
+            for (int i = 0; i < filters.size() && i < whens.size(); i++) {
                 WhenDefinition when = whens.get(i);
                 FilterProcessor filter = filters.get(i);
 
@@ -82,11 +86,12 @@ public class ManagedChoice extends ManagedProcessor 
implements ManagedChoiceMBea
 
                 CompositeData data = new CompositeDataSupport(
                         ct,
-                        new String[] { "predicate", "language", "matches" },
-                        new Object[] { predicate, language, matches });
+                        new String[] { "index", "predicate", "language", 
"matches" },
+                        new Object[] { answer.size(), predicate, language, 
matches });
                 answer.put(data);
             }
-            if (getDefinition().getOtherwise() != null) {
+            if (getDefinition().getOtherwise() != null
+                    && !ProcessorReifier.isDisabled(getContext(), 
getDefinition().getOtherwise())) {
                 CompositeType ct = CamelOpenMBeanTypes.choiceCompositeType();
                 String predicate = "otherwise";
                 String language = "";
@@ -94,8 +99,8 @@ public class ManagedChoice extends ManagedProcessor 
implements ManagedChoiceMBea
 
                 CompositeData data = new CompositeDataSupport(
                         ct,
-                        new String[] { "predicate", "language", "matches" },
-                        new Object[] { predicate, language, matches });
+                        new String[] { "index", "predicate", "language", 
"matches" },
+                        new Object[] { answer.size(), predicate, language, 
matches });
                 answer.put(data);
             }
 
diff --git 
a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedDoTry.java
 
b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedDoTry.java
index 22289a667b5b..dcfcfedc1c0b 100644
--- 
a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedDoTry.java
+++ 
b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedDoTry.java
@@ -84,8 +84,8 @@ public class ManagedDoTry extends ManagedProcessor implements 
ManagedDoTryMBean
 
                         CompositeData data = new CompositeDataSupport(
                                 ct,
-                                new String[] { "exception", "predicate", 
"language", "matches" },
-                                new Object[] { fqn, predicate, language, 
matches });
+                                new String[] { "index", "exception", 
"predicate", "language", "matches" },
+                                new Object[] { answer.size(), fqn, predicate, 
language, matches });
                         answer.put(data);
                     }
                 }
diff --git 
a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedDynamicRouter.java
 
b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedDynamicRouter.java
index dadb79d8f63c..814691ef59d4 100644
--- 
a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedDynamicRouter.java
+++ 
b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedDynamicRouter.java
@@ -16,22 +16,14 @@
  */
 package org.apache.camel.management.mbean;
 
-import java.util.Map;
-
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.CompositeType;
 import javax.management.openmbean.TabularData;
-import javax.management.openmbean.TabularDataSupport;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.api.management.ManagedResource;
-import org.apache.camel.api.management.mbean.CamelOpenMBeanTypes;
 import org.apache.camel.api.management.mbean.ManagedDynamicRouterMBean;
 import org.apache.camel.model.DynamicRouterDefinition;
 import org.apache.camel.processor.DynamicRouter;
-import org.apache.camel.spi.EndpointUtilizationStatistics;
 import org.apache.camel.spi.ManagementStrategy;
 import org.apache.camel.util.URISupport;
 
@@ -111,28 +103,7 @@ public class ManagedDynamicRouter extends ManagedProcessor 
implements ManagedDyn
     @Override
     public TabularData extendedInformation() {
         try {
-            TabularData answer = new 
TabularDataSupport(CamelOpenMBeanTypes.endpointsUtilizationTabularType());
-
-            EndpointUtilizationStatistics stats = 
getProcessor().getEndpointUtilizationStatistics();
-            if (stats != null) {
-                for (Map.Entry<String, Long> entry : 
stats.getStatistics().entrySet()) {
-                    CompositeType ct = 
CamelOpenMBeanTypes.endpointsUtilizationCompositeType();
-                    String url = entry.getKey();
-                    if (sanitize) {
-                        url = URISupport.sanitizeUri(url);
-                    }
-
-                    Long hits = entry.getValue();
-                    if (hits == null) {
-                        hits = 0L;
-                    }
-
-                    CompositeData data
-                            = new CompositeDataSupport(ct, new String[] { 
"url", "hits" }, new Object[] { url, hits });
-                    answer.put(data);
-                }
-            }
-            return answer;
+            return 
EndpointUtilizationHelper.toTabularData(getProcessor().getEndpointUtilizationStatistics(),
 sanitize);
         } catch (Exception e) {
             throw RuntimeCamelException.wrapRuntimeCamelException(e);
         }
diff --git 
a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedEndpointRegistry.java
 
b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedEndpointRegistry.java
index 7f93b0d1db83..1ed7bd26e49b 100644
--- 
a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedEndpointRegistry.java
+++ 
b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedEndpointRegistry.java
@@ -17,6 +17,8 @@
 package org.apache.camel.management.mbean;
 
 import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
 
 import javax.management.openmbean.CompositeData;
 import javax.management.openmbean.CompositeDataSupport;
@@ -89,15 +91,20 @@ public class ManagedEndpointRegistry extends ManagedService 
implements ManagedEn
         try {
             TabularData answer = new 
TabularDataSupport(CamelOpenMBeanTypes.listEndpointsTabularType());
             Collection<Endpoint> endpoints = endpointRegistry.values();
+            Set<String> urls = new HashSet<>();
             for (Endpoint endpoint : endpoints) {
                 CompositeType ct = 
CamelOpenMBeanTypes.listEndpointsCompositeType();
                 String url = endpoint.getEndpointUri();
+                // look up by the real uri (and not the sanitized)
+                boolean fromStatic = endpointRegistry.isStatic(url);
+                boolean fromDynamic = endpointRegistry.isDynamic(url);
                 if (sanitize) {
                     url = URISupport.sanitizeUri(url);
                 }
-
-                boolean fromStatic = endpointRegistry.isStatic(url);
-                boolean fromDynamic = endpointRegistry.isDynamic(url);
+                if (!urls.add(url)) {
+                    // endpoints that only differ in a secret are the same url 
when sanitized
+                    continue;
+                }
 
                 CompositeData data = new CompositeDataSupport(
                         ct, new String[] { "url", "static", "dynamic" }, new 
Object[] { url, fromStatic, fromDynamic });
diff --git 
a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedEnricher.java
 
b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedEnricher.java
index dff6cdc211a6..cf1b9a8a5dc9 100644
--- 
a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedEnricher.java
+++ 
b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedEnricher.java
@@ -16,22 +16,14 @@
  */
 package org.apache.camel.management.mbean;
 
-import java.util.Map;
-
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.CompositeType;
 import javax.management.openmbean.TabularData;
-import javax.management.openmbean.TabularDataSupport;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.api.management.ManagedResource;
-import org.apache.camel.api.management.mbean.CamelOpenMBeanTypes;
 import org.apache.camel.api.management.mbean.ManagedEnricherMBean;
 import org.apache.camel.model.EnrichDefinition;
 import org.apache.camel.processor.Enricher;
-import org.apache.camel.spi.EndpointUtilizationStatistics;
 import org.apache.camel.spi.ManagementStrategy;
 import org.apache.camel.util.URISupport;
 
@@ -126,28 +118,7 @@ public class ManagedEnricher extends ManagedProcessor 
implements ManagedEnricher
     @Override
     public TabularData extendedInformation() {
         try {
-            TabularData answer = new 
TabularDataSupport(CamelOpenMBeanTypes.endpointsUtilizationTabularType());
-
-            EndpointUtilizationStatistics stats = 
getProcessor().getEndpointUtilizationStatistics();
-            if (stats != null) {
-                for (Map.Entry<String, Long> entry : 
stats.getStatistics().entrySet()) {
-                    CompositeType ct = 
CamelOpenMBeanTypes.endpointsUtilizationCompositeType();
-                    String url = entry.getKey();
-                    if (sanitize) {
-                        url = URISupport.sanitizeUri(url);
-                    }
-
-                    Long hits = entry.getValue();
-                    if (hits == null) {
-                        hits = 0L;
-                    }
-
-                    CompositeData data
-                            = new CompositeDataSupport(ct, new String[] { 
"url", "hits" }, new Object[] { url, hits });
-                    answer.put(data);
-                }
-            }
-            return answer;
+            return 
EndpointUtilizationHelper.toTabularData(getProcessor().getEndpointUtilizationStatistics(),
 sanitize);
         } catch (Exception e) {
             throw RuntimeCamelException.wrapRuntimeCamelException(e);
         }
diff --git 
a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedPoll.java
 
b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedPoll.java
index fc11ccaa8262..1206d36fa3a9 100644
--- 
a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedPoll.java
+++ 
b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedPoll.java
@@ -16,22 +16,14 @@
  */
 package org.apache.camel.management.mbean;
 
-import java.util.Map;
-
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.CompositeType;
 import javax.management.openmbean.TabularData;
-import javax.management.openmbean.TabularDataSupport;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.api.management.ManagedResource;
-import org.apache.camel.api.management.mbean.CamelOpenMBeanTypes;
 import org.apache.camel.api.management.mbean.ManagedPollMBean;
 import org.apache.camel.model.PollDefinition;
 import org.apache.camel.processor.PollProcessor;
-import org.apache.camel.spi.EndpointUtilizationStatistics;
 import org.apache.camel.spi.ManagementStrategy;
 import org.apache.camel.util.URISupport;
 
@@ -96,28 +88,7 @@ public class ManagedPoll extends ManagedProcessor implements 
ManagedPollMBean {
     @Override
     public TabularData extendedInformation() {
         try {
-            TabularData answer = new 
TabularDataSupport(CamelOpenMBeanTypes.endpointsUtilizationTabularType());
-
-            EndpointUtilizationStatistics stats = 
getProcessor().getEndpointUtilizationStatistics();
-            if (stats != null) {
-                for (Map.Entry<String, Long> entry : 
stats.getStatistics().entrySet()) {
-                    CompositeType ct = 
CamelOpenMBeanTypes.endpointsUtilizationCompositeType();
-                    String url = entry.getKey();
-                    if (sanitize) {
-                        url = URISupport.sanitizeUri(url);
-                    }
-
-                    Long hits = entry.getValue();
-                    if (hits == null) {
-                        hits = 0L;
-                    }
-
-                    CompositeData data
-                            = new CompositeDataSupport(ct, new String[] { 
"url", "hits" }, new Object[] { url, hits });
-                    answer.put(data);
-                }
-            }
-            return answer;
+            return 
EndpointUtilizationHelper.toTabularData(getProcessor().getEndpointUtilizationStatistics(),
 sanitize);
         } catch (Exception e) {
             throw RuntimeCamelException.wrapRuntimeCamelException(e);
         }
diff --git 
a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedPollEnricher.java
 
b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedPollEnricher.java
index 0f9a9c89d6d4..d167159e9f70 100644
--- 
a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedPollEnricher.java
+++ 
b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedPollEnricher.java
@@ -16,22 +16,14 @@
  */
 package org.apache.camel.management.mbean;
 
-import java.util.Map;
-
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.CompositeType;
 import javax.management.openmbean.TabularData;
-import javax.management.openmbean.TabularDataSupport;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.api.management.ManagedResource;
-import org.apache.camel.api.management.mbean.CamelOpenMBeanTypes;
 import org.apache.camel.api.management.mbean.ManagedPollEnricherMBean;
 import org.apache.camel.model.PollEnrichDefinition;
 import org.apache.camel.processor.PollEnricher;
-import org.apache.camel.spi.EndpointUtilizationStatistics;
 import org.apache.camel.spi.ManagementStrategy;
 import org.apache.camel.util.URISupport;
 
@@ -131,28 +123,7 @@ public class ManagedPollEnricher extends ManagedProcessor 
implements ManagedPoll
     @Override
     public TabularData extendedInformation() {
         try {
-            TabularData answer = new 
TabularDataSupport(CamelOpenMBeanTypes.endpointsUtilizationTabularType());
-
-            EndpointUtilizationStatistics stats = 
getProcessor().getEndpointUtilizationStatistics();
-            if (stats != null) {
-                for (Map.Entry<String, Long> entry : 
stats.getStatistics().entrySet()) {
-                    CompositeType ct = 
CamelOpenMBeanTypes.endpointsUtilizationCompositeType();
-                    String url = entry.getKey();
-                    if (sanitize) {
-                        url = URISupport.sanitizeUri(url);
-                    }
-
-                    Long hits = entry.getValue();
-                    if (hits == null) {
-                        hits = 0L;
-                    }
-
-                    CompositeData data
-                            = new CompositeDataSupport(ct, new String[] { 
"url", "hits" }, new Object[] { url, hits });
-                    answer.put(data);
-                }
-            }
-            return answer;
+            return 
EndpointUtilizationHelper.toTabularData(getProcessor().getEndpointUtilizationStatistics(),
 sanitize);
         } catch (Exception e) {
             throw RuntimeCamelException.wrapRuntimeCamelException(e);
         }
diff --git 
a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedRecipientList.java
 
b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedRecipientList.java
index a3f434834869..7bb272ac7642 100644
--- 
a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedRecipientList.java
+++ 
b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedRecipientList.java
@@ -16,22 +16,14 @@
  */
 package org.apache.camel.management.mbean;
 
-import java.util.Map;
-
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.CompositeType;
 import javax.management.openmbean.TabularData;
-import javax.management.openmbean.TabularDataSupport;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.api.management.ManagedResource;
-import org.apache.camel.api.management.mbean.CamelOpenMBeanTypes;
 import org.apache.camel.api.management.mbean.ManagedRecipientListMBean;
 import org.apache.camel.model.RecipientListDefinition;
 import org.apache.camel.processor.RecipientList;
-import org.apache.camel.spi.EndpointUtilizationStatistics;
 import org.apache.camel.spi.ManagementStrategy;
 import org.apache.camel.util.URISupport;
 
@@ -131,28 +123,7 @@ public class ManagedRecipientList extends ManagedProcessor 
implements ManagedRec
     @Override
     public TabularData extendedInformation() {
         try {
-            TabularData answer = new 
TabularDataSupport(CamelOpenMBeanTypes.endpointsUtilizationTabularType());
-
-            EndpointUtilizationStatistics stats = 
getProcessor().getEndpointUtilizationStatistics();
-            if (stats != null) {
-                for (Map.Entry<String, Long> entry : 
stats.getStatistics().entrySet()) {
-                    CompositeType ct = 
CamelOpenMBeanTypes.endpointsUtilizationCompositeType();
-                    String url = entry.getKey();
-                    if (sanitize) {
-                        url = URISupport.sanitizeUri(url);
-                    }
-
-                    Long hits = entry.getValue();
-                    if (hits == null) {
-                        hits = 0L;
-                    }
-
-                    CompositeData data
-                            = new CompositeDataSupport(ct, new String[] { 
"url", "hits" }, new Object[] { url, hits });
-                    answer.put(data);
-                }
-            }
-            return answer;
+            return 
EndpointUtilizationHelper.toTabularData(getProcessor().getEndpointUtilizationStatistics(),
 sanitize);
         } catch (Exception e) {
             throw RuntimeCamelException.wrapRuntimeCamelException(e);
         }
diff --git 
a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedRoutingSlip.java
 
b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedRoutingSlip.java
index d62a5f1acfbf..ed8fc0bccb20 100644
--- 
a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedRoutingSlip.java
+++ 
b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedRoutingSlip.java
@@ -16,22 +16,14 @@
  */
 package org.apache.camel.management.mbean;
 
-import java.util.Map;
-
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.CompositeType;
 import javax.management.openmbean.TabularData;
-import javax.management.openmbean.TabularDataSupport;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.api.management.ManagedResource;
-import org.apache.camel.api.management.mbean.CamelOpenMBeanTypes;
 import org.apache.camel.api.management.mbean.ManagedRoutingSlipMBean;
 import org.apache.camel.model.RoutingSlipDefinition;
 import org.apache.camel.processor.RoutingSlip;
-import org.apache.camel.spi.EndpointUtilizationStatistics;
 import org.apache.camel.spi.ManagementStrategy;
 import org.apache.camel.util.URISupport;
 
@@ -106,28 +98,7 @@ public class ManagedRoutingSlip extends ManagedProcessor 
implements ManagedRouti
     @Override
     public TabularData extendedInformation() {
         try {
-            TabularData answer = new 
TabularDataSupport(CamelOpenMBeanTypes.endpointsUtilizationTabularType());
-
-            EndpointUtilizationStatistics stats = 
getProcessor().getEndpointUtilizationStatistics();
-            if (stats != null) {
-                for (Map.Entry<String, Long> entry : 
stats.getStatistics().entrySet()) {
-                    CompositeType ct = 
CamelOpenMBeanTypes.endpointsUtilizationCompositeType();
-                    String url = entry.getKey();
-                    if (sanitize) {
-                        url = URISupport.sanitizeUri(url);
-                    }
-
-                    Long hits = entry.getValue();
-                    if (hits == null) {
-                        hits = 0L;
-                    }
-
-                    CompositeData data
-                            = new CompositeDataSupport(ct, new String[] { 
"url", "hits" }, new Object[] { url, hits });
-                    answer.put(data);
-                }
-            }
-            return answer;
+            return 
EndpointUtilizationHelper.toTabularData(getProcessor().getEndpointUtilizationStatistics(),
 sanitize);
         } catch (Exception e) {
             throw RuntimeCamelException.wrapRuntimeCamelException(e);
         }
diff --git 
a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedSendDynamicProcessor.java
 
b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedSendDynamicProcessor.java
index 4c8b51a4072c..8d7ecbcb9f94 100644
--- 
a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedSendDynamicProcessor.java
+++ 
b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedSendDynamicProcessor.java
@@ -16,22 +16,14 @@
  */
 package org.apache.camel.management.mbean;
 
-import java.util.Map;
-
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.CompositeType;
 import javax.management.openmbean.TabularData;
-import javax.management.openmbean.TabularDataSupport;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.api.management.ManagedResource;
-import org.apache.camel.api.management.mbean.CamelOpenMBeanTypes;
 import org.apache.camel.api.management.mbean.ManagedSendDynamicProcessorMBean;
 import org.apache.camel.model.ProcessorDefinition;
 import org.apache.camel.processor.SendDynamicProcessor;
-import org.apache.camel.spi.EndpointUtilizationStatistics;
 import org.apache.camel.spi.ManagementStrategy;
 import org.apache.camel.util.URISupport;
 
@@ -126,28 +118,7 @@ public class ManagedSendDynamicProcessor extends 
ManagedProcessor implements Man
     @Override
     public TabularData extendedInformation() {
         try {
-            TabularData answer = new 
TabularDataSupport(CamelOpenMBeanTypes.endpointsUtilizationTabularType());
-
-            EndpointUtilizationStatistics stats = 
getProcessor().getEndpointUtilizationStatistics();
-            if (stats != null) {
-                for (Map.Entry<String, Long> entry : 
stats.getStatistics().entrySet()) {
-                    CompositeType ct = 
CamelOpenMBeanTypes.endpointsUtilizationCompositeType();
-                    String url = entry.getKey();
-                    if (sanitize) {
-                        url = URISupport.sanitizeUri(url);
-                    }
-
-                    Long hits = entry.getValue();
-                    if (hits == null) {
-                        hits = 0L;
-                    }
-
-                    CompositeData data
-                            = new CompositeDataSupport(ct, new String[] { 
"url", "hits" }, new Object[] { url, hits });
-                    answer.put(data);
-                }
-            }
-            return answer;
+            return 
EndpointUtilizationHelper.toTabularData(getProcessor().getEndpointUtilizationStatistics(),
 sanitize);
         } catch (Exception e) {
             throw RuntimeCamelException.wrapRuntimeCamelException(e);
         }
diff --git 
a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedTaskManagerRegistry.java
 
b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedTaskManagerRegistry.java
index 96d529312f04..e9da27164927 100644
--- 
a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedTaskManagerRegistry.java
+++ 
b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedTaskManagerRegistry.java
@@ -65,9 +65,11 @@ public class ManagedTaskManagerRegistry extends 
ManagedService implements Manage
                 CompositeData data = new CompositeDataSupport(
                         ct,
                         new String[] {
-                                "name", "kind", "status", "attempts", "delay", 
"elapsed", "firstTime", "lastTime", "nextTime",
-                                "failure" },
-                        new Object[] { name, kind, status, attempts, delay, 
elapsed, firstTime, lastTime, nextTime, failure });
+                                "index", "name", "kind", "status", "attempts", 
"delay", "elapsed", "firstTime", "lastTime",
+                                "nextTime", "failure" },
+                        new Object[] {
+                                answer.size(), name, kind, status, attempts, 
delay, elapsed, firstTime, lastTime, nextTime,
+                                failure });
                 answer.put(data);
             }
             return answer;
diff --git 
a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedWireTapProcessor.java
 
b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedWireTapProcessor.java
index 2dcf55c7fa31..4281c29176f5 100644
--- 
a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedWireTapProcessor.java
+++ 
b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedWireTapProcessor.java
@@ -16,22 +16,14 @@
  */
 package org.apache.camel.management.mbean;
 
-import java.util.Map;
-
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.CompositeType;
 import javax.management.openmbean.TabularData;
-import javax.management.openmbean.TabularDataSupport;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.api.management.ManagedResource;
-import org.apache.camel.api.management.mbean.CamelOpenMBeanTypes;
 import org.apache.camel.api.management.mbean.ManagedWireTapMBean;
 import org.apache.camel.model.ProcessorDefinition;
 import org.apache.camel.processor.WireTapProcessor;
-import org.apache.camel.spi.EndpointUtilizationStatistics;
 import org.apache.camel.spi.ManagementStrategy;
 import org.apache.camel.util.URISupport;
 
@@ -112,28 +104,7 @@ public class ManagedWireTapProcessor extends 
ManagedProcessor implements Managed
     @Override
     public TabularData extendedInformation() {
         try {
-            TabularData answer = new 
TabularDataSupport(CamelOpenMBeanTypes.endpointsUtilizationTabularType());
-
-            EndpointUtilizationStatistics stats = 
getProcessor().getEndpointUtilizationStatistics();
-            if (stats != null) {
-                for (Map.Entry<String, Long> entry : 
stats.getStatistics().entrySet()) {
-                    CompositeType ct = 
CamelOpenMBeanTypes.endpointsUtilizationCompositeType();
-                    String url = entry.getKey();
-                    if (sanitize) {
-                        url = URISupport.sanitizeUri(url);
-                    }
-
-                    Long hits = entry.getValue();
-                    if (hits == null) {
-                        hits = 0L;
-                    }
-
-                    CompositeData data
-                            = new CompositeDataSupport(ct, new String[] { 
"url", "hits" }, new Object[] { url, hits });
-                    answer.put(data);
-                }
-            }
-            return answer;
+            return 
EndpointUtilizationHelper.toTabularData(getProcessor().getEndpointUtilizationStatistics(),
 sanitize);
         } catch (Exception e) {
             throw RuntimeCamelException.wrapRuntimeCamelException(e);
         }
diff --git 
a/core/camel-management/src/test/java/org/apache/camel/management/ManagedTabularDataEdgeCasesTest.java
 
b/core/camel-management/src/test/java/org/apache/camel/management/ManagedTabularDataEdgeCasesTest.java
new file mode 100644
index 000000000000..41835d5118c0
--- /dev/null
+++ 
b/core/camel-management/src/test/java/org/apache/camel/management/ManagedTabularDataEdgeCasesTest.java
@@ -0,0 +1,201 @@
+/*
+ * 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.management;
+
+import java.io.IOException;
+import java.time.Duration;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.TabularData;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.ManagementStatisticsLevel;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.model.ChoiceDefinition;
+import org.apache.camel.processor.aggregate.UseLatestAggregationStrategy;
+import org.apache.camel.support.task.BackgroundTask;
+import org.apache.camel.support.task.Tasks;
+import org.apache.camel.support.task.budget.Budgets;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.DisabledOnOs;
+import org.junit.jupiter.api.condition.OS;
+
+import static 
org.apache.camel.management.DefaultManagementObjectNameStrategy.TYPE_PROCESSOR;
+import static org.awaitility.Awaitility.await;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+@DisabledOnOs(OS.AIX)
+public class ManagedTabularDataEdgeCasesTest extends ManagementTestSupport {
+
+    @Override
+    protected CamelContext createCamelContext() throws Exception {
+        CamelContext context = super.createCamelContext();
+        
context.getManagementStrategy().getManagementAgent().setStatisticsLevel(ManagementStatisticsLevel.Extended);
+        return context;
+    }
+
+    private ObjectName service(String name) throws Exception {
+        return getMBeanServer().queryNames(new 
ObjectName("*:type=services,*"), null).stream()
+                .filter(n -> 
n.getCanonicalName().contains(name)).findFirst().orElseThrow();
+    }
+
+    private static CompositeData row(TabularData data, String item, Object 
value) {
+        return data.values().stream().map(CompositeData.class::cast)
+                .filter(cd -> 
value.equals(cd.get(item))).findFirst().orElseThrow();
+    }
+
+    @Test
+    public void testChoiceWithSamePredicateTwice() throws Exception {
+        template.sendBodyAndHeader("direct:choice", "Hello", "type", "b");
+
+        TabularData data = (TabularData) 
getMBeanServer().invoke(getCamelObjectName(TYPE_PROCESSOR, "myChoice"),
+                "extendedInformation", null, null);
+        // two whens with the same predicate (such as with different outputs 
for the same condition) and otherwise
+        assertEquals(3, data.size());
+    }
+
+    @Test
+    public void testChoiceWithDisabledWhen() throws Exception {
+        template.sendBodyAndHeader("direct:disabled", "Hello", "b", "true");
+
+        TabularData data = (TabularData) 
getMBeanServer().invoke(getCamelObjectName(TYPE_PROCESSOR, "disabledChoice"),
+                "extendedInformation", null, null);
+        CompositeData b = row(data, "predicate", "${header.b}");
+        assertEquals(1L, b.get("matches"));
+    }
+
+    @Test
+    public void testDoTryWithSameExceptionTwice() throws Exception {
+        // caught by the first doCatch (onWhen), and by the second
+        template.sendBodyAndHeader("direct:try", "Hello", "a", "x");
+        template.sendBodyAndHeader("direct:try", "Hello", "a", "y");
+
+        TabularData data = (TabularData) 
getMBeanServer().invoke(getCamelObjectName(TYPE_PROCESSOR, "myTry"),
+                "extendedInformation", null, null);
+        assertEquals(2, data.size());
+    }
+
+    @Test
+    public void testEndpointUtilizationWithSecrets() throws Exception {
+        template.sendBodyAndHeader("direct:dynamic", "Hello", "pw", "a");
+        template.sendBodyAndHeader("direct:dynamic", "Hello", "pw", "b");
+
+        TabularData data = (TabularData) 
getMBeanServer().invoke(getCamelObjectName(TYPE_PROCESSOR, "myToD"),
+                "extendedInformation", null, null);
+        // the two endpoints only differ in the password, which is masked
+        assertEquals(1, data.size());
+        assertEquals(2L, ((CompositeData) 
data.values().iterator().next()).get("hits"));
+    }
+
+    @Test
+    public void testExchangeFactoryOfSameUri() throws Exception {
+        TabularData data = (TabularData) 
getMBeanServer().invoke(service("DefaultExchangeFactoryManager"),
+                "listStatistics", null, null);
+        assertTrue(data.size() >= 2);
+    }
+
+    @Test
+    public void testListEndpointsWithSecrets() throws Exception {
+        context.getEndpoint("mock:secret?password=a");
+        context.getEndpoint("mock:secret?password=b");
+
+        TabularData data = (TabularData) 
getMBeanServer().invoke(service("DefaultEndpointRegistry"),
+                "listEndpoints", null, null);
+        CompositeData row = row(data, "url", "mock://result?password=xxxxxx");
+        assertEquals(true, row.get("static"));
+    }
+
+    @Test
+    public void testListTasksWithSameName() throws Exception {
+        ScheduledExecutorService executor = 
Executors.newScheduledThreadPool(2);
+        try {
+            for (int i = 0; i < 2; i++) {
+                BackgroundTask.BackgroundTaskBuilder builder = 
Tasks.backgroundTask();
+                builder.withName("same");
+                builder.withScheduledExecutor(executor)
+                        
.withBudget(Budgets.timeBudget().withInterval(Duration.ofMillis(100))
+                                
.withMaxDuration(Duration.ofSeconds(5)).build())
+                        .build()
+                        .schedule(context, () -> false);
+            }
+            MBeanServer mbeanServer = getMBeanServer();
+            ObjectName on = service("DefaultTaskManagerRegistry");
+            await().atMost(3, TimeUnit.SECONDS).untilAsserted(() -> {
+                TabularData data = (TabularData) mbeanServer.invoke(on, 
"listTasks", null, null);
+                assertEquals(2, data.size());
+            });
+        } finally {
+            executor.shutdownNow();
+        }
+    }
+
+    @Test
+    public void testAggregateForceCompletionOnStop() throws Exception {
+        MBeanServer mbeanServer = getMBeanServer();
+        ObjectName on = getCamelObjectName(TYPE_PROCESSOR, "myAggregate");
+        assertEquals(Boolean.TRUE, mbeanServer.getAttribute(on, 
"ForceCompletionOnStop"));
+        assertEquals(Boolean.FALSE, mbeanServer.getAttribute(on, 
"CompletionFromBatchConsumer"));
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                from("direct:choice")
+                        .choice().id("myChoice")
+                            .when(simple("${header.type} == 'a'")).to("mock:a")
+                            .when(simple("${header.type} == 'a'")).to("mock:b")
+                            .otherwise().to("mock:c")
+                        .end();
+
+                ChoiceDefinition choice = 
from("direct:disabled").choice().id("disabledChoice");
+                choice.when(simple("${header.a}")).to("mock:a")
+                        .when(simple("${header.b}")).to("mock:b")
+                        .end();
+                choice.getWhenClauses().get(0).setDisabled("true");
+
+                from("direct:try")
+                        .doTry().id("myTry")
+                            .throwException(new IOException("Forced"))
+                        
.doCatch(IOException.class).onWhen(header("a").isEqualTo("x"))
+                            .to("mock:io1")
+                        .doCatch(IOException.class)
+                            .to("mock:io2")
+                        .end();
+
+                
from("direct:dynamic").toD("mock:secret?password=${header.pw}").id("myToD");
+
+                
from("seda:foo?multipleConsumers=true").routeId("foo1").to("mock:foo1");
+                
from("seda:foo?multipleConsumers=true").routeId("foo2").to("mock:foo2");
+
+                from("direct:result").to("mock:result?password=secret");
+
+                from("direct:aggregate")
+                        .aggregate(header("id"), new 
UseLatestAggregationStrategy()).completionSize(5)
+                        .forceCompletionOnStop().id("myAggregate")
+                        .to("mock:aggregated");
+            }
+        };
+    }
+}
diff --git 
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc 
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc
index 863807b29d5e..ec73dfa2e638 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc
@@ -401,6 +401,13 @@ The `dynamic-router` endpoint gained an `allowedSchemes` 
option, an optional com
 allow-list of component schemes that a subscription destination may resolve 
to. It is unset by
 default, which allows any scheme, matching the previous behaviour.
 
+=== camel-management - JMX tabular data
+
+Some tabular data returned by the JMX MBeans had a key that was not unique, so 
the operation failed with
+`KeyAlreadyExistsException`. The tabular data of the Choice EIP and doTry EIP 
`extendedInformation` and of
+`listTasks` of the task manager registry now have an `index` item as their 
key, the exchange factories of `listStatistics`
+are keyed by `url` and `routeId`, and endpoints that only differ in a secret 
(which is masked) are shown once.
+
 === camel-exec
 
 `allowControlHeaders` is now annotated `security = "insecure:dev"`.

Reply via email to