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
commit f59a19a4f1412481b3f7d7e54868f18d14380b0a Author: Claus Ibsen <[email protected]> AuthorDate: Fri Jul 10 20:01:27 2026 +0200 chore: fix NPEs, sort bugs, and filter issues in CLI cmd/process commands - CamelRouteGroupStatus: null-check routeGroups array, fix sort group comparing name vs group, move limit after sorting - CamelRouteStatus: null-check stackTrace in error table, move limit after sorting so top-N works correctly - CamelContextTop: move rows.add after field population to avoid garbage rows - CamelContextStatus: null-safe reload error message via Objects.toString - CamelCount: assign row.uptime so --sort age works - ListMetric: add tags check to counters, gauges and distributions filters - Jolokia: print error message when no integration matches - Hawtio: skip disconnect when pid is 0 - CamelTraceAction/CamelReceiveAction: fix t2 fallback assignment and use getOrDefault to avoid NPE on first use - LoggerAction: use name filter instead of wildcard in callList - CamelReceiveAction: default to all pids for status and fix filter - CamelStubAction: sort by queue name instead of integration name - RouteControllerAction/CamelSourceTop/CamelThreadDump: null-check arrays from empty JSON response - ActionBaseCommand: return null after interrupt instead of busy-spinning Co-Authored-By: Claude Opus 4.6 <[email protected]> Signed-off-by: Claus Ibsen <[email protected]> --- .../dsl/jbang/core/commands/action/ActionBaseCommand.java | 1 + .../dsl/jbang/core/commands/action/CamelReceiveAction.java | 10 +++++----- .../camel/dsl/jbang/core/commands/action/CamelSourceTop.java | 4 ++++ .../dsl/jbang/core/commands/action/CamelStubAction.java | 4 +++- .../dsl/jbang/core/commands/action/CamelThreadDump.java | 8 ++++++-- .../dsl/jbang/core/commands/action/CamelTraceAction.java | 6 +++--- .../camel/dsl/jbang/core/commands/action/LoggerAction.java | 2 +- .../jbang/core/commands/action/RouteControllerAction.java | 4 ++++ .../dsl/jbang/core/commands/process/CamelContextStatus.java | 3 ++- .../dsl/jbang/core/commands/process/CamelContextTop.java | 2 +- .../camel/dsl/jbang/core/commands/process/CamelCount.java | 3 ++- .../jbang/core/commands/process/CamelRouteGroupStatus.java | 12 ++++++++---- .../dsl/jbang/core/commands/process/CamelRouteStatus.java | 9 +++++---- .../apache/camel/dsl/jbang/core/commands/process/Hawtio.java | 4 +++- .../camel/dsl/jbang/core/commands/process/Jolokia.java | 1 + .../camel/dsl/jbang/core/commands/process/ListMetric.java | 9 ++++++--- 16 files changed, 55 insertions(+), 27 deletions(-) diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/ActionBaseCommand.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/ActionBaseCommand.java index ffa8a4915601..8e4025432245 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/ActionBaseCommand.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/ActionBaseCommand.java @@ -63,6 +63,7 @@ abstract class ActionBaseCommand extends CamelCommand { } } catch (InterruptedException e) { Thread.currentThread().interrupt(); + return null; } catch (Exception e) { // ignore } diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelReceiveAction.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelReceiveAction.java index 65e39b7d8f94..57d5c16708cc 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelReceiveAction.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelReceiveAction.java @@ -420,10 +420,10 @@ public class CamelReceiveAction extends ActionBaseCommand { } else if (name != null) { pids = findPids(name); } else { - return 0; + pids = findPids("*"); } ProcessHandle.allProcesses() - .filter(ph -> pid == 0 && pids.contains(ph.pid())) + .filter(ph -> pids.contains(ph.pid())) .forEach(ph -> { JsonObject root = loadStatus(ph.pid()); if (root != null) { @@ -808,10 +808,10 @@ public class CamelReceiveAction extends ActionBaseCommand { long t1 = r1.timestamp; long t2 = r2.timestamp; if (t1 == 0) { - t1 = lastTimestamp.get(r1.name); + t1 = lastTimestamp.getOrDefault(r1.name, 0L); } - if (t1 == 0) { - t1 = lastTimestamp.get(r2.name); + if (t2 == 0) { + t2 = lastTimestamp.getOrDefault(r2.name, 0L); } if (t1 == 0 && t2 == 0) { return 0; diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelSourceTop.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelSourceTop.java index c5adb41a09cd..0cd102cd2344 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelSourceTop.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelSourceTop.java @@ -86,6 +86,10 @@ public class CamelSourceTop extends ActionWatchCommand { JsonObject jo = waitForOutputFile(outputFile); if (jo != null) { JsonArray arr = (JsonArray) jo.get("processors"); + if (arr == null) { + printer().printErr("Source top data not available from the running integration"); + return 0; + } for (int i = 0; i < arr.size(); i++) { JsonObject o = (JsonObject) arr.get(i); Row row = new Row(); diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelStubAction.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelStubAction.java index 500873bd1202..a784e8317bb6 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelStubAction.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelStubAction.java @@ -256,7 +256,9 @@ public class CamelStubAction extends ActionWatchCommand { } switch (s) { case "name": - return o1.name.compareToIgnoreCase(o2.name) * negate; + String q1 = o1.queue != null ? o1.queue : ""; + String q2 = o2.queue != null ? o2.queue : ""; + return q1.compareToIgnoreCase(q2) * negate; case "total": return Integer.compare(o1.size, o2.size) * negate; default: diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelThreadDump.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelThreadDump.java index 8843aa4c5579..207f2e65c07f 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelThreadDump.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelThreadDump.java @@ -134,6 +134,10 @@ public class CamelThreadDump extends ActionWatchCommand { JsonObject jo = waitForOutputFile(outputFile); if (jo != null) { JsonArray arr = (JsonArray) jo.get("threads"); + if (arr == null) { + printer().printErr("Thread dump data not available from the running integration"); + return 0; + } for (int i = 0; i < arr.size(); i++) { JsonObject jt = (JsonObject) arr.get(i); @@ -177,8 +181,8 @@ public class CamelThreadDump extends ActionWatchCommand { clearScreen(); } if (!rows.isEmpty()) { - int total = jo.getInteger("threadCount"); - int peak = jo.getInteger("peakThreadCount"); + int total = jo.getIntegerOrDefault("threadCount", 0); + int peak = jo.getIntegerOrDefault("peakThreadCount", 0); printer().printf("PID: %s\tThreads: %d\tPeak: %d\t\tDisplay: %d/%d%n", pid, total, peak, rows.size(), total); if (depth == 1) { diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelTraceAction.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelTraceAction.java index e51f723eb5e2..0c90cc4573c3 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelTraceAction.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelTraceAction.java @@ -660,10 +660,10 @@ public class CamelTraceAction extends ActionBaseCommand { long t1 = r1.timestamp; long t2 = r2.timestamp; if (t1 == 0) { - t1 = lastTimestamp.get(r1.name); + t1 = lastTimestamp.getOrDefault(r1.name, 0L); } - if (t1 == 0) { - t1 = lastTimestamp.get(r2.name); + if (t2 == 0) { + t2 = lastTimestamp.getOrDefault(r2.name, 0L); } if (t1 == 0 && t2 == 0) { return 0; diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/LoggerAction.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/LoggerAction.java index 624e1385a637..dd5e172d208e 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/LoggerAction.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/LoggerAction.java @@ -93,7 +93,7 @@ public class LoggerAction extends ActionBaseCommand { protected Integer callList() { List<Row> rows = new ArrayList<>(); - List<Long> pids = findPids("*"); + List<Long> pids = findPids(name); ProcessHandle.allProcesses() .filter(ph -> pids.contains(ph.pid())) .forEach(ph -> { diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/RouteControllerAction.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/RouteControllerAction.java index d6a8022b54d5..82ea1ac8f646 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/RouteControllerAction.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/RouteControllerAction.java @@ -122,6 +122,10 @@ public class RouteControllerAction extends ActionWatchCommand { supervising = "SupervisingRouteController".equals(jo.getString("controller")); JsonArray arr = (JsonArray) jo.get("routes"); + if (arr == null) { + printer().printErr("Route controller data not available from the running integration"); + return 0; + } for (int i = 0; i < arr.size(); i++) { JsonObject jt = (JsonObject) arr.get(i); diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelContextStatus.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelContextStatus.java index 15780358eef7..15afd78dd9d9 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelContextStatus.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelContextStatus.java @@ -20,6 +20,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.stream.Collectors; import com.github.freva.asciitable.AsciiTable; @@ -146,7 +147,7 @@ public class CamelContextStatus extends ProcessWatchCommand { row.reloadedFailed = stats.get("failed").toString(); stats = (Map<String, ?>) stats.get("lastError"); if (stats != null) { - row.reloadedError = stats.get("message").toString(); + row.reloadedError = Objects.toString(stats.get("message"), ""); } } } diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelContextTop.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelContextTop.java index 79a1e6963209..b5f656ac96a6 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelContextTop.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelContextTop.java @@ -82,7 +82,6 @@ public class CamelContextTop extends ProcessWatchCommand { // there must be a status file for the running Camel integration if (root != null) { Row row = new Row(); - rows.add(row); JsonObject context = (JsonObject) root.get("context"); if (context == null) { return; @@ -143,6 +142,7 @@ public class CamelContextTop extends ProcessWatchCommand { row.gcCount = gc.getLong("collectionCount"); row.gcTime = gc.getLong("collectionTime"); } + rows.add(row); } }); diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelCount.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelCount.java index b181b2370d76..a2b6492c74bb 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelCount.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelCount.java @@ -84,7 +84,8 @@ public class CamelCount extends ProcessWatchCommand { row.name = ProcessHelper.extractName(root, ph); } row.pid = Long.toString(ph.pid()); - row.age = TimeUtils.printSince(extractSince(ph)); + row.uptime = extractSince(ph); + row.age = TimeUtils.printSince(row.uptime); Map<String, ?> stats = context.getMap("statistics"); if (stats != null) { row.total = stats.get("exchangesTotal").toString(); diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelRouteGroupStatus.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelRouteGroupStatus.java index 960c4d3cd38e..f655a5dffde1 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelRouteGroupStatus.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelRouteGroupStatus.java @@ -99,6 +99,9 @@ public class CamelRouteGroupStatus extends ProcessWatchCommand { return; } JsonArray array = (JsonArray) root.get("routeGroups"); + if (array == null) { + return; + } for (int i = 0; i < array.size(); i++) { JsonObject o = (JsonObject) array.get(i); Row row = new Row(); @@ -173,9 +176,6 @@ public class CamelRouteGroupStatus extends ProcessWatchCommand { if (mean > 0 && (row.mean == null || Long.parseLong(row.mean) < mean)) { add = false; } - if (limit > 0 && rows.size() >= limit) { - add = false; - } if (add && filter != null) { boolean match = false; for (String f : filter) { @@ -200,6 +200,10 @@ public class CamelRouteGroupStatus extends ProcessWatchCommand { // sort rows rows.sort(this::sortRow); + if (limit > 0 && rows.size() > limit) { + rows.subList(limit, rows.size()).clear(); + } + if (!rows.isEmpty()) { printTable(rows); } @@ -270,7 +274,7 @@ public class CamelRouteGroupStatus extends ProcessWatchCommand { case "name": return o1.name.compareToIgnoreCase(o2.name) * negate; case "group": - return o1.name.compareToIgnoreCase(o2.group) * negate; + return o1.group.compareToIgnoreCase(o2.group) * negate; case "age": return Long.compare(o1.uptime, o2.uptime) * negate; default: diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelRouteStatus.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelRouteStatus.java index 70ef00c2e468..7c0f4add2155 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelRouteStatus.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelRouteStatus.java @@ -215,9 +215,6 @@ public class CamelRouteStatus extends ProcessWatchCommand { if (mean > 0 && (row.mean == null || Long.parseLong(row.mean) < mean)) { add = false; } - if (limit > 0 && rows.size() >= limit) { - add = false; - } if (add && filter != null) { boolean match = false; for (String f : filter) { @@ -248,6 +245,10 @@ public class CamelRouteStatus extends ProcessWatchCommand { // sort rows rows.sort(this::sortRow); + if (limit > 0 && rows.size() > limit) { + rows.subList(limit, rows.size()).clear(); + } + if (!rows.isEmpty()) { if (error) { for (Row r : rows) { @@ -369,7 +370,7 @@ public class CamelRouteStatus extends ProcessWatchCommand { new Column().header("MESSAGE").dataAlign(HorizontalAlign.LEFT) .maxWidth(msgW, OverflowBehaviour.NEWLINE) .with(r -> r.lastErrorMessage)))); - if (!er.stackTrace.isEmpty()) { + if (er.stackTrace != null && !er.stackTrace.isEmpty()) { printer().println(); printer().println(StringHelper.fillChars('-', 120)); printer().println(StringHelper.padString(1, 55) + "STACK-TRACE"); diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/Hawtio.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/Hawtio.java index 0fdee11a213f..b9b63c71000d 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/Hawtio.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/Hawtio.java @@ -78,7 +78,9 @@ public class Hawtio extends CamelCommand { exit = callHawtio(); } } finally { - disconnectJolokia(); + if (pid != 0) { + disconnectJolokia(); + } } } return exit; diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/Jolokia.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/Jolokia.java index 9759810ccdb3..1c6490dc029a 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/Jolokia.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/Jolokia.java @@ -63,6 +63,7 @@ public class Jolokia extends ProcessBaseCommand { public Integer doCall() throws Exception { List<Long> pids = findPids(name); if (pids.isEmpty()) { + printer().printErr("No running Camel integration matches: " + name); return 1; } else if (pids.size() > 1) { printer().println("Name or pid " + name + " matches " + pids.size() diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/ListMetric.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/ListMetric.java index 8573ff77a986..bfd68b3073f8 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/ListMetric.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/ListMetric.java @@ -119,7 +119,8 @@ public class ListMetric extends ProcessWatchCommand { if (!all && getNumber(row.count).isEmpty()) { continue; } - if (filter == null || row.type.equals(filter) || row.metricName.contains(filter)) { + if (filter == null || row.type.equals(filter) || row.metricName.contains(filter) + || row.tags.contains(filter)) { rows.add(row); } } @@ -172,7 +173,8 @@ public class ListMetric extends ProcessWatchCommand { if (!all && getNumber(row.count).isEmpty()) { continue; } - if (filter == null || row.type.equals(filter) || row.metricName.contains(filter)) { + if (filter == null || row.type.equals(filter) || row.metricName.contains(filter) + || row.tags.contains(filter)) { rows.add(row); } } @@ -198,7 +200,8 @@ public class ListMetric extends ProcessWatchCommand { if (!all && getNumber(row.count).isEmpty()) { continue; } - if (filter == null || row.type.equals(filter) || row.metricName.contains(filter)) { + if (filter == null || row.type.equals(filter) || row.metricName.contains(filter) + || row.tags.contains(filter)) { rows.add(row); } }
