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 3ad447c4bee5 CAMEL-26427: camel-jbang - Every CLI command waits 300 ms
before the JVM exits (#28762)
3ad447c4bee5 is described below
commit 3ad447c4bee5268b3eff0bd700c40a2c365d0d1a
Author: Claus Ibsen <[email protected]>
AuthorDate: Sat Oct 31 08:31:15 2026 +0100
CAMEL-26427: camel-jbang - Every CLI command waits 300 ms before the JVM
exits (#28762)
Signed-off-by: Claus Ibsen <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---
.../camel/dsl/jbang/core/commands/Harden.java | 21 +++++++++++++++------
.../dsl/jbang/core/commands/CamelJBangMainTest.java | 18 ++++++++++++++++++
2 files changed, 33 insertions(+), 6 deletions(-)
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Harden.java
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Harden.java
index 2ad81ad4358b..63461f1e5382 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Harden.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Harden.java
@@ -197,9 +197,18 @@ public class Harden extends CamelCommand {
// whether the answer for the current file was printed as it came (reset
per file)
private boolean streamed;
- private final HttpClient httpClient = HttpClient.newBuilder()
- .connectTimeout(Duration.ofSeconds(CONNECT_TIMEOUT_SECONDS))
- .build();
+ // created on first use: the CLI creates all its commands at startup, and
the selector thread of a client makes the
+ // JVM wait up to 300 ms when it exits
+ private HttpClient httpClient;
+
+ private HttpClient httpClient() {
+ if (httpClient == null) {
+ httpClient = HttpClient.newBuilder()
+
.connectTimeout(Duration.ofSeconds(CONNECT_TIMEOUT_SECONDS))
+ .build();
+ }
+ return httpClient;
+ }
public Harden(CamelJBangMain main) {
super(main);
@@ -370,7 +379,7 @@ public class Harden extends CamelCommand {
.timeout(Duration.ofSeconds(HEALTH_CHECK_TIMEOUT_SECONDS))
.GET()
.build();
- HttpResponse<String> response = httpClient.send(request,
HttpResponse.BodyHandlers.ofString());
+ HttpResponse<String> response = httpClient().send(request,
HttpResponse.BodyHandlers.ofString());
return response.statusCode() == 200;
} catch (Exception e) {
return false;
@@ -628,7 +637,7 @@ public class Harden extends CamelCommand {
.POST(HttpRequest.BodyPublishers.ofString(body.toJson()))
.build();
- HttpResponse<Stream<String>> response = httpClient.send(
+ HttpResponse<Stream<String>> response = httpClient().send(
request, HttpResponse.BodyHandlers.ofLines());
if (response.statusCode() != 200) {
@@ -678,7 +687,7 @@ public class Harden extends CamelCommand {
builder.header("Authorization", "Bearer " + authKey);
}
- HttpResponse<String> response = httpClient.send(builder.build(),
HttpResponse.BodyHandlers.ofString());
+ HttpResponse<String> response = httpClient().send(builder.build(),
HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
return (JsonObject) Jsoner.deserialize(response.body());
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMainTest.java
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMainTest.java
index f017fadbbd10..ab1e9c1b3060 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMainTest.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMainTest.java
@@ -18,12 +18,14 @@ package org.apache.camel.dsl.jbang.core.commands;
import java.lang.reflect.Field;
import java.util.List;
+import java.util.Set;
import org.apache.camel.dsl.jbang.core.common.PluginHelper;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import picocli.CommandLine;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -66,4 +68,20 @@ class CamelJBangMainTest extends CamelCommandBaseTestSupport
{
List<String> output = printer.getLines();
assertFalse(output.stream().anyMatch(l -> l.contains("Plugins (not
installed):")));
}
+
+ @Test
+ public void creatingTheCommandsStartsNoThread() {
+ // the CLI creates all its commands at startup: a thread that a
command starts when it is created is in every
+ // run, and a thread in native code when the JVM exits (such as the
selector of an HTTP client) makes every
+ // command wait up to 300 ms before the JVM exits
+ Set<Thread> before = Thread.getAllStackTraces().keySet();
+
+ main.newCommandLine();
+
+ List<String> started = Thread.getAllStackTraces().keySet().stream()
+ .filter(t -> !before.contains(t) && t.isAlive())
+ .map(Thread::getName)
+ .toList();
+ assertEquals(List.of(), started, "Threads started by creating the
commands of the CLI");
+ }
}