This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch camel-4.22.x
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/camel-4.22.x by this push:
new ead30881a4da [backport camel-4.22.x] CAMEL-25620: camel-console -
allow dev consoles to be registered while the registry starts (#27808)
ead30881a4da is described below
commit ead30881a4dad0ec9e9ed55b39ced3f841c4f9cb
Author: Guillaume Nodet <[email protected]>
AuthorDate: Wed Oct 14 13:45:45 2026 +0200
[backport camel-4.22.x] CAMEL-25620: camel-console - allow dev consoles to
be registered while the registry starts (#27808)
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
---
.../impl/console/DefaultDevConsoleRegistry.java | 21 ++++-----
.../console/DefaultDevConsoleRegistryTest.java | 55 ++++++++++++++++++++++
2 files changed, 65 insertions(+), 11 deletions(-)
diff --git
a/core/camel-console/src/main/java/org/apache/camel/impl/console/DefaultDevConsoleRegistry.java
b/core/camel-console/src/main/java/org/apache/camel/impl/console/DefaultDevConsoleRegistry.java
index 8b6c2b882c32..3146b8bae1c9 100644
---
a/core/camel-console/src/main/java/org/apache/camel/impl/console/DefaultDevConsoleRegistry.java
+++
b/core/camel-console/src/main/java/org/apache/camel/impl/console/DefaultDevConsoleRegistry.java
@@ -19,7 +19,7 @@ package org.apache.camel.impl.console;
import java.util.Collection;
import java.util.Comparator;
import java.util.Set;
-import java.util.TreeSet;
+import java.util.concurrent.ConcurrentSkipListSet;
import java.util.stream.Stream;
import org.apache.camel.CamelContext;
@@ -56,8 +56,9 @@ public class DefaultDevConsoleRegistry extends ServiceSupport
implements DevCons
}
public DefaultDevConsoleRegistry(CamelContext camelContext) {
- // sort by id
- this.consoles = new TreeSet<>(Comparator.comparing(DevConsole::getId));
+ // sort by id, and allow consoles to be registered while the registry
is iterating its consoles
+ // (such as camel-cli-connector resolving consoles while camel is
starting)
+ this.consoles = new
ConcurrentSkipListSet<>(Comparator.comparing(DevConsole::getId));
setCamelContext(camelContext);
}
@@ -120,8 +121,10 @@ public class DefaultDevConsoleRegistry extends
ServiceSupport implements DevCons
if (answer == null) {
DevConsoleResolver resolver =
PluginHelper.getDevConsoleResolver(camelContext);
answer = resolver.resolveDevConsole(id);
- if (answer != null) {
- register(answer);
+ if (answer != null && !register(answer)) {
+ // another thread registered the console in the meantime, so
use that one
+ DevConsole resolved = answer;
+ answer = consoles.stream().filter(h ->
h.getId().equals(id)).findFirst().orElse(resolved);
}
}
@@ -130,12 +133,8 @@ public class DefaultDevConsoleRegistry extends
ServiceSupport implements DevCons
@Override
public boolean register(DevConsole console) {
- boolean result;
- // do we have this already
- if (getConsole(console.getId()).isPresent()) {
- return false;
- }
- result = consoles.add(console);
+ // the consoles are sorted by id, so adding a console with an id that
is already registered is rejected
+ boolean result = consoles.add(console);
if (result) {
CamelContextAware.trySetCamelContext(console, camelContext);
// ensure console is started as it may be registered later
diff --git
a/core/camel-console/src/test/java/org/apache/camel/impl/console/DefaultDevConsoleRegistryTest.java
b/core/camel-console/src/test/java/org/apache/camel/impl/console/DefaultDevConsoleRegistryTest.java
index 4e5af79bd7d0..79538b1581c8 100644
---
a/core/camel-console/src/test/java/org/apache/camel/impl/console/DefaultDevConsoleRegistryTest.java
+++
b/core/camel-console/src/test/java/org/apache/camel/impl/console/DefaultDevConsoleRegistryTest.java
@@ -16,10 +16,13 @@
*/
package org.apache.camel.impl.console;
+import java.util.Map;
+
import org.apache.camel.ContextTestSupport;
import org.apache.camel.console.DevConsole;
import org.apache.camel.console.DevConsoleRegistry;
import org.apache.camel.support.PluginHelper;
+import org.apache.camel.support.console.AbstractDevConsole;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@@ -74,4 +77,56 @@ public class DefaultDevConsoleRegistryTest extends
ContextTestSupport {
Assertions.assertTrue(unregistered);
Assertions.assertFalse(registry.getConsole("custom-test").isPresent());
}
+
+ @Test
+ public void testRegisterWhileStarting() throws Exception {
+ DefaultDevConsoleRegistry registry = new
DefaultDevConsoleRegistry(context);
+ registry.start();
+
+ // a console that registers another console when started, such as
camel-cli-connector
+ // resolving consoles from its own thread while the registry is
starting its consoles
+ DevConsole first = new TestConsole("a-first") {
+ @Override
+ protected void doStart() throws Exception {
+ registry.register(new TestConsole("z-late-" +
registry.stream().count()));
+ }
+ };
+ registry.register(first);
+ registry.register(new TestConsole("b-second"));
+ registry.stop();
+
+ // starting again registers a console while the registry iterates its
consoles
+ registry.start();
+
+ Assertions.assertTrue(registry.getConsole("a-first").isPresent());
+ Assertions.assertTrue(registry.getConsole("b-second").isPresent());
+ Assertions.assertEquals(4, registry.stream().count());
+ }
+
+ @Test
+ public void testRegisterSameIdTwice() {
+ DefaultDevConsoleRegistry registry = new
DefaultDevConsoleRegistry(context);
+
+ DevConsole console = new TestConsole("same");
+ Assertions.assertTrue(registry.register(console));
+ Assertions.assertFalse(registry.register(new TestConsole("same")));
+ Assertions.assertSame(console,
registry.getConsole("same").orElse(null));
+ }
+
+ private static class TestConsole extends AbstractDevConsole {
+
+ TestConsole(String id) {
+ super("test", id, id, id);
+ }
+
+ @Override
+ protected Map<String, Object> doCallJson(Map<String, Object> options) {
+ return Map.of();
+ }
+
+ @Override
+ protected String doCallText(Map<String, Object> options) {
+ return "";
+ }
+ }
}