You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2025/08/04 18:18:43 UTC

(camel) branch main updated: CAMEL-22315: camel-core: Backlog debugger should have skip over step (#18817)

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 671f31bc32b CAMEL-22315: camel-core: Backlog debugger should have skip over step (#18817)
671f31bc32b is described below

commit 671f31bc32b1f464a93b300c10fcf7d5bf735753
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Aug 4 20:18:37 2025 +0200

    CAMEL-22315: camel-core: Backlog debugger should have skip over step (#18817)
---
 .../java/org/apache/camel/ExchangeConstantProvider.java  |  3 ++-
 .../src/main/java/org/apache/camel/Exchange.java         |  1 +
 .../main/java/org/apache/camel/ExchangePropertyKey.java  |  3 +++
 .../src/main/java/org/apache/camel/MessageHistory.java   | 10 ++++++++++
 .../main/java/org/apache/camel/spi/BacklogDebugger.java  |  5 +++++
 .../camel/impl/debugger/DefaultBacklogDebugger.java      | 12 ++++++++++++
 .../apache/camel/impl/engine/CamelInternalProcessor.java | 16 ++++++++++++++++
 .../org/apache/camel/impl/console/DebugDevConsole.java   |  3 +++
 .../camel/main/DefaultConfigurationProperties.java       | 11 ++++++-----
 .../management/mbean/ManagedBacklogDebuggerMBean.java    |  3 +++
 .../camel/management/mbean/ManagedBacklogDebugger.java   |  5 +++++
 .../org/apache/camel/support/DefaultMessageHistory.java  | 11 +++++++++++
 .../user-manual/modules/ROOT/pages/backlog-debugger.adoc |  4 +++-
 .../org/apache/camel/dsl/jbang/core/commands/Debug.java  | 14 +++++++++++---
 14 files changed, 91 insertions(+), 10 deletions(-)

diff --git a/core/camel-api/src/generated/java/org/apache/camel/ExchangeConstantProvider.java b/core/camel-api/src/generated/java/org/apache/camel/ExchangeConstantProvider.java
index 51dfe0d93d7..9af5075afb0 100644
--- a/core/camel-api/src/generated/java/org/apache/camel/ExchangeConstantProvider.java
+++ b/core/camel-api/src/generated/java/org/apache/camel/ExchangeConstantProvider.java
@@ -13,7 +13,7 @@ public class ExchangeConstantProvider {
 
     private static final Map<String, String> MAP;
     static {
-        Map<String, String> map = new HashMap<>(161);
+        Map<String, String> map = new HashMap<>(162);
         map.put("ACCEPT_CONTENT_TYPE", "CamelAcceptContentType");
         map.put("AGGREGATED_COLLECTION_GUARD", "CamelAggregatedCollectionGuard");
         map.put("AGGREGATED_COMPLETED_BY", "CamelAggregatedCompletedBy");
@@ -146,6 +146,7 @@ public class ExchangeConstantProvider {
         map.put("SAXPARSER_FACTORY", "CamelSAXParserFactory");
         map.put("SCHEDULER_POLLED_MESSAGES", "CamelSchedulerPolledMessages");
         map.put("SKIP_GZIP_ENCODING", "CamelSkipGzipEncoding");
+        map.put("SKIP_OVER", "CamelSkipOver");
         map.put("SKIP_WWW_FORM_URLENCODED", "CamelSkipWwwFormUrlEncoding");
         map.put("SLIP_ENDPOINT", "CamelSlipEndpoint");
         map.put("SLIP_PRODUCER", "CamelSlipProducer");
diff --git a/core/camel-api/src/main/java/org/apache/camel/Exchange.java b/core/camel-api/src/main/java/org/apache/camel/Exchange.java
index 7ac40e9981b..da6a6bfe08c 100644
--- a/core/camel-api/src/main/java/org/apache/camel/Exchange.java
+++ b/core/camel-api/src/main/java/org/apache/camel/Exchange.java
@@ -287,6 +287,7 @@ public interface Exchange extends VariableAware {
     @Deprecated(since = "3.15.0")
     String SOAP_ACTION = "CamelSoapAction";
     String SKIP_GZIP_ENCODING = "CamelSkipGzipEncoding";
+    String SKIP_OVER = "CamelSkipOver";
     String SKIP_WWW_FORM_URLENCODED = "CamelSkipWwwFormUrlEncoding";
     @Metadata(label = "routingSlip", description = "The endpoint uri of this routing slip", javaType = "String")
     String SLIP_ENDPOINT = "CamelSlipEndpoint";
diff --git a/core/camel-api/src/main/java/org/apache/camel/ExchangePropertyKey.java b/core/camel-api/src/main/java/org/apache/camel/ExchangePropertyKey.java
index 8caf3a56e7a..97b8c0bd7c2 100644
--- a/core/camel-api/src/main/java/org/apache/camel/ExchangePropertyKey.java
+++ b/core/camel-api/src/main/java/org/apache/camel/ExchangePropertyKey.java
@@ -71,6 +71,7 @@ public enum ExchangePropertyKey {
     PARENT_UNIT_OF_WORK(Exchange.PARENT_UNIT_OF_WORK),
     RECEIVED_TIMESTAMP(Exchange.RECEIVED_TIMESTAMP),
     RECIPIENT_LIST_ENDPOINT(Exchange.RECIPIENT_LIST_ENDPOINT),
+    SKIP_OVER(Exchange.SKIP_OVER),
     SLIP_ENDPOINT(Exchange.SLIP_ENDPOINT),
     SLIP_PRODUCER(Exchange.SLIP_PRODUCER),
     SPLIT_COMPLETE(Exchange.SPLIT_COMPLETE),
@@ -191,6 +192,8 @@ public enum ExchangePropertyKey {
                 return RECEIVED_TIMESTAMP;
             case Exchange.RECIPIENT_LIST_ENDPOINT:
                 return RECIPIENT_LIST_ENDPOINT;
+            case Exchange.SKIP_OVER:
+                return SKIP_OVER;
             case Exchange.SLIP_ENDPOINT:
                 return SLIP_ENDPOINT;
             case Exchange.SLIP_PRODUCER:
diff --git a/core/camel-api/src/main/java/org/apache/camel/MessageHistory.java b/core/camel-api/src/main/java/org/apache/camel/MessageHistory.java
index 38a5dbca676..42deab6c8c2 100644
--- a/core/camel-api/src/main/java/org/apache/camel/MessageHistory.java
+++ b/core/camel-api/src/main/java/org/apache/camel/MessageHistory.java
@@ -70,4 +70,14 @@ public interface MessageHistory {
      */
     boolean isAcceptDebugger();
 
+    /**
+     * Used specially during debugging to know that an EIP was skipped over
+     */
+    void setDebugSkipOver(boolean skipOver);
+
+    /**
+     * Used specially during debugging to know that an EIP was skipped over
+     */
+    boolean isDebugSkipOver();
+
 }
diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/BacklogDebugger.java b/core/camel-api/src/main/java/org/apache/camel/spi/BacklogDebugger.java
index 24dd4846ba0..cba446fba1e 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/BacklogDebugger.java
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/BacklogDebugger.java
@@ -286,6 +286,11 @@ public interface BacklogDebugger extends StatefulService {
      */
     void stepOver();
 
+    /**
+     * To skip over (does not call the node) to next node when in single step mode.
+     */
+    void skipOver();
+
     /**
      * Gets node ids for all current suspended exchanges at breakpoints
      */
diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/debugger/DefaultBacklogDebugger.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/debugger/DefaultBacklogDebugger.java
index a594c4d510a..af167ed56b9 100644
--- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/debugger/DefaultBacklogDebugger.java
+++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/debugger/DefaultBacklogDebugger.java
@@ -79,6 +79,7 @@ public final class DefaultBacklogDebugger extends ServiceSupport implements Back
     private final AtomicReference<CountDownLatch> suspend = new AtomicReference<>();
     private final Deque<String> singleStepExchangeId = new ArrayDeque<>();
     private final AtomicBoolean stepOverMode = new AtomicBoolean();
+    private final AtomicBoolean skipOverMode = new AtomicBoolean();
 
     private boolean suspendMode;
     private String initialBreakpoints;
@@ -644,9 +645,13 @@ public final class DefaultBacklogDebugger extends ServiceSupport implements Back
             suspendedBreakpointMessages.remove(node);
             SuspendedExchange se = suspendedBreakpoints.remove(node);
             if (se != null) {
+                if (skipOverMode.get()) {
+                    se.getExchange().setProperty(ExchangePropertyKey.SKIP_OVER, Boolean.TRUE);
+                }
                 se.getLatch().countDown();
             }
         }
+        skipOverMode.set(false);
     }
 
     @Override
@@ -655,6 +660,12 @@ public final class DefaultBacklogDebugger extends ServiceSupport implements Back
         step();
     }
 
+    @Override
+    public void skipOver() {
+        skipOverMode.set(true);
+        step();
+    }
+
     @Override
     public Set<String> getSuspendedBreakpointNodeIds() {
         return new LinkedHashSet<>(suspendedBreakpoints.keySet());
@@ -1012,6 +1023,7 @@ public final class DefaultBacklogDebugger extends ServiceSupport implements Back
         @Override
         public void afterProcess(Exchange exchange, Processor processor, NamedNode definition, long timeTaken) {
             stepOverMode.set(false);
+            skipOverMode.set(false);
         }
 
         @Override
diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/CamelInternalProcessor.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/CamelInternalProcessor.java
index a9eb63950fa..a3766d842d1 100644
--- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/CamelInternalProcessor.java
+++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/CamelInternalProcessor.java
@@ -323,6 +323,22 @@ public class CamelInternalProcessor extends DelegateAsyncProcessor implements In
             }
         }
 
+        // debugger can skip processing the exchange
+        Object skip = exchange.removeProperty(ExchangePropertyKey.SKIP_OVER);
+        if (Boolean.TRUE == skip) {
+            if (LOG.isTraceEnabled()) {
+                LOG.trace("Skipping exchange for exchangeId: {} -> {}", exchange.getExchangeId(), exchange);
+            }
+            List<MessageHistory> list = exchange.getProperty(ExchangePropertyKey.MESSAGE_HISTORY, List.class);
+            if (list != null && !list.isEmpty()) {
+                MessageHistory last = list.get(list.size() - 1);
+                last.setDebugSkipOver(true);
+            }
+            // skip because the processor is specially disabled (such as from debugger)
+            originalCallback.done(true);
+            return true;
+        }
+
         if (exchange.isTransacted()) {
             return processTransacted(exchange, afterTask);
         }
diff --git a/core/camel-console/src/main/java/org/apache/camel/impl/console/DebugDevConsole.java b/core/camel-console/src/main/java/org/apache/camel/impl/console/DebugDevConsole.java
index c1ac690a827..d8e4f021b08 100644
--- a/core/camel-console/src/main/java/org/apache/camel/impl/console/DebugDevConsole.java
+++ b/core/camel-console/src/main/java/org/apache/camel/impl/console/DebugDevConsole.java
@@ -126,6 +126,8 @@ public class DebugDevConsole extends AbstractDevConsole {
             }
         } else if ("stepover".equalsIgnoreCase(command)) {
             backlog.stepOver();
+        } else if ("skipover".equalsIgnoreCase(command)) {
+            backlog.skipOver();
         } else if ("add".equalsIgnoreCase(command) && ObjectHelper.isNotEmpty(breakpoint)) {
             backlog.addBreakpoint(breakpoint);
         } else if ("remove".equalsIgnoreCase(command)) {
@@ -244,6 +246,7 @@ public class DebugDevConsole extends AbstractDevConsole {
             }
             jo.put("elapsed", h.getElapsed());
             jo.put("acceptDebugger", h.isAcceptDebugger());
+            jo.put("skipOver", h.isDebugSkipOver());
             if (h.getNode() != null) {
                 jo.put("nodeId", h.getNode().getId());
                 if (h.getNode().getLocation() != null) {
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationProperties.java b/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationProperties.java
index 7baf3a7946a..c10fb6838e0 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationProperties.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationProperties.java
@@ -322,13 +322,14 @@ public abstract class DefaultConfigurationProperties<T> {
     }
 
     /**
-     * Directory to load additional properties files that contains configurations that takes precedence
-     * (except for camel.main.xxx configurations).
+     * Directory to load additional properties files that contains configurations that takes precedence (except for
+     * camel.main.xxx configurations).
      *
-     * This can be used to refer to files that may have secret configuration that has been mounted on the file system for containers.
+     * This can be used to refer to files that may have secret configuration that has been mounted on the file system
+     * for containers.
      *
-     * You can specify a pattern to load from file-system (not classpath) and a name pattern such as /var/app/secret/*.properties,
-     * multiple directories can be separated by comma.
+     * You can specify a pattern to load from file-system (not classpath) and a name pattern such as
+     * /var/app/secret/*.properties, multiple directories can be separated by comma.
      */
     public void setFileConfigurations(String fileConfigurations) {
         this.fileConfigurations = fileConfigurations;
diff --git a/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedBacklogDebuggerMBean.java b/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedBacklogDebuggerMBean.java
index 3bdcceb26b2..2c318990dd3 100644
--- a/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedBacklogDebuggerMBean.java
+++ b/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedBacklogDebuggerMBean.java
@@ -98,6 +98,9 @@ public interface ManagedBacklogDebuggerMBean {
     @ManagedOperation(description = "Steps over the next node in step mode")
     void stepOver();
 
+    @ManagedOperation(description = "Skips over the next node in step mode")
+    void skipOver();
+
     @ManagedOperation(description = "Return the node ids which has breakpoints")
     Set<String> breakpoints();
 
diff --git a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedBacklogDebugger.java b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedBacklogDebugger.java
index a80ac72bb0f..bb14a1bcbd2 100644
--- a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedBacklogDebugger.java
+++ b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedBacklogDebugger.java
@@ -206,6 +206,11 @@ public class ManagedBacklogDebugger implements ManagedBacklogDebuggerMBean {
         backlogDebugger.stepOver();
     }
 
+    @Override
+    public void skipOver() {
+        backlogDebugger.skipOver();
+    }
+
     @Override
     public Set<String> suspendedBreakpointNodeIds() {
         return backlogDebugger.getSuspendedBreakpointNodeIds();
diff --git a/core/camel-support/src/main/java/org/apache/camel/support/DefaultMessageHistory.java b/core/camel-support/src/main/java/org/apache/camel/support/DefaultMessageHistory.java
index 936058103c4..a8293d7eb61 100644
--- a/core/camel-support/src/main/java/org/apache/camel/support/DefaultMessageHistory.java
+++ b/core/camel-support/src/main/java/org/apache/camel/support/DefaultMessageHistory.java
@@ -31,6 +31,7 @@ public class DefaultMessageHistory implements MessageHistory {
     private final MonotonicClock clock = new MonotonicClock();
     private final Message message;
     private boolean acceptDebugger;
+    private boolean debugSkipOver;
     private long elapsed;
 
     public DefaultMessageHistory(String routeId, NamedNode node) {
@@ -84,6 +85,16 @@ public class DefaultMessageHistory implements MessageHistory {
         return acceptDebugger;
     }
 
+    @Override
+    public boolean isDebugSkipOver() {
+        return debugSkipOver;
+    }
+
+    @Override
+    public void setDebugSkipOver(boolean debugSkipOver) {
+        this.debugSkipOver = debugSkipOver;
+    }
+
     @Override
     public String toString() {
         return "DefaultMessageHistory["
diff --git a/docs/user-manual/modules/ROOT/pages/backlog-debugger.adoc b/docs/user-manual/modules/ROOT/pages/backlog-debugger.adoc
index 349c189ab9e..53ad7b33b44 100644
--- a/docs/user-manual/modules/ROOT/pages/backlog-debugger.adoc
+++ b/docs/user-manual/modules/ROOT/pages/backlog-debugger.adoc
@@ -57,7 +57,9 @@ NOTE: This requires to enabled JMX by including `camel-management` JAR in the cl
 |`setMessageBodyOnBreakpoint(nodeId,body)` |`void` |To update the message body on the suspended Exchange at the node.
 |`setMessageHeaderOnBreakpoint(nodeId,headerName,value)` |`void` |To update/add the message header on the suspended Exchange at the node.
 |`stepBreakpoint(nodeId)` |`void` |To start single step mode from a suspended breakpoint at the given node. Then invoke `step` to step to next node in the route.
-|`step` |`void` |To step to next node when in single step mode.
+|`step` |`void` |To step into the next node when in single step mode.
+|`stepOver` |`void` |To step over the next node when in single step mode.
+|`skipOver` |`void` |To skip over the next node when in single step mode.
 |`validateConditionalBreakpoint` |`String` |Used for validating if a given predicate is valid or not. Returns null if valid, otherwise a string with the error message.
 |`messageHistoryOnBreakpointAsXml(nodeId)` |`String` |Returns message history at the given node Id in XML format
 |=======================================================================
diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Debug.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Debug.java
index a1de3e1db54..49531f09b7e 100644
--- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Debug.java
+++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Debug.java
@@ -223,6 +223,8 @@ public class Debug extends Run {
                     String cmd = "step";
                     if (line.equalsIgnoreCase("o") || line.equalsIgnoreCase("over")) {
                         cmd = "stepover";
+                    } else if (line.equalsIgnoreCase("s") || line.equalsIgnoreCase("skip")) {
+                        cmd = "skipover";
                     }
                     sendDebugCommand(spawnPid, cmd, null);
                 }
@@ -438,6 +440,7 @@ public class Debug extends Run {
                                     history.routeId = line.getString("routeId");
                                     history.nodeId = line.getString("nodeId");
                                     history.elapsed = line.getLongOrDefault("elapsed", 0);
+                                    history.skipOver = line.getBooleanOrDefault("skipOver", false);
                                     history.location = line.getString("location");
                                     history.line = line.getIntegerOrDefault("line", -1);
                                     history.code = line.getString("code");
@@ -471,6 +474,7 @@ public class Debug extends Run {
                 this.waitForUser.set(true);
             }
             if (this.waitForUser.get()) {
+                boolean first = this.suspendedRow != null && this.suspendedRow.first;
                 // save current message to file
                 if (output != null && this.suspendedRow != null) {
                     JsonObject j = this.suspendedRow.message;
@@ -492,10 +496,10 @@ public class Debug extends Run {
                 }
 
                 String msg;
-                if (isStepOverSupported(version)) {
-                    msg = "    Breakpoint suspended (i = step into (default), o = step over). Press ENTER to continue.";
+                if (!first && isStepOverSupported(version)) {
+                    msg = "    Breakpoint suspended (i = step into (default), o = step over, s = skip over). Press ENTER to continue (q = quit).";
                 } else {
-                    msg = "    Breakpoint suspended. Press ENTER to continue.";
+                    msg = "    Breakpoint suspended. Press ENTER to continue (q = quit).";
                 }
                 if (loggingColor) {
                     AnsiConsole.out().println(Ansi.ansi().a(Ansi.Attribute.INTENSITY_BOLD).a(msg).reset());
@@ -603,6 +607,9 @@ public class Debug extends Run {
                     }
                     long e = i == 2 ? 0 : h.elapsed; // the pseudo from should have 0 as elapsed
                     String elapsed = "(" + e + "ms)";
+                    if (h.skipOver) {
+                        elapsed = "(skipped)";
+                    }
 
                     String c = "";
                     if (h.code != null) {
@@ -861,6 +868,7 @@ public class Debug extends Run {
         String routeId;
         String nodeId;
         long elapsed;
+        boolean skipOver;
         String location;
         int line;
         String code;