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 e48475ad95a Standby (#12039)
e48475ad95a is described below
commit e48475ad95aae03ec39bc388809b72b69964b111
Author: Claus Ibsen <[email protected]>
AuthorDate: Fri Nov 17 14:53:37 2023 +0100
Standby (#12039)
* CAMEL-20067: camel-core - Add debuggingStandby option
* CAMEL-20067: camel-core - Add debuggingStandby option
---
.../main/camel-main-configuration-metadata.json | 1 +
.../component/debug/CamelDebuggerFactory.java | 5 +-
.../main/java/org/apache/camel/CamelContext.java | 12 ++
.../java/org/apache/camel/spi/BacklogDebugger.java | 16 +++
.../impl/debugger/DefaultBacklogDebugger.java | 15 ++-
.../camel/impl/engine/AbstractCamelContext.java | 13 ++-
.../apache/camel/impl/engine/DefaultChannel.java | 2 +-
.../apache/camel/impl/console/DebugDevConsole.java | 8 +-
.../apache/camel/impl/CamelContextConfigurer.java | 6 +
.../DebuggerConfigurationPropertiesConfigurer.java | 6 +
.../camel-main-configuration-metadata.json | 1 +
core/camel-main/src/main/docs/main.adoc | 3 +-
.../org/apache/camel/main/BaseMainSupport.java | 11 +-
.../main/DebuggerConfigurationProperties.java | 23 ++++
.../camel/main/DefaultConfigurationConfigurer.java | 5 +
.../mbean/ManagedBacklogDebuggerMBean.java | 3 +
.../management/mbean/ManagedBacklogDebugger.java | 5 +
.../management/BacklogDebuggerStandbyTest.java | 126 +++++++++++++++++++++
.../camel/management/BacklogDebuggerTest.java | 3 +
19 files changed, 255 insertions(+), 9 deletions(-)
diff --git
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json
index 8e56959bc3c..b5d6c587081 100644
---
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json
+++
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json
@@ -153,6 +153,7 @@
{ "name": "camel.debug.includeExchangeProperties", "description": "Whether
to include the exchange properties in the traced message", "sourceType":
"org.apache.camel.main.DebuggerConfigurationProperties", "type": "boolean",
"javaType": "boolean", "defaultValue": true },
{ "name": "camel.debug.loggingLevel", "description": "The debugger logging
level to use when logging activity.", "sourceType":
"org.apache.camel.main.DebuggerConfigurationProperties", "type": "object",
"javaType": "org.apache.camel.LoggingLevel", "defaultValue": "INFO", "enum": [
"ERROR", "WARN", "INFO", "DEBUG", "TRACE", "OFF" ] },
{ "name": "camel.debug.singleStepIncludeStartEnd", "description": "In
single step mode, then when the exchange is created and completed, then
simulate a breakpoint at start and end, that allows to suspend and watch the
incoming\/complete exchange at the route (you can see message body as response,
failed exception etc).", "sourceType":
"org.apache.camel.main.DebuggerConfigurationProperties", "type": "boolean",
"javaType": "boolean", "defaultValue": "false" },
+ { "name": "camel.debug.standby", "description": "To set the debugger in
standby mode, where the debugger will be installed by not automatic enabled.
The debugger can then later be enabled explicit from Java, JMX or tooling.",
"sourceType": "org.apache.camel.main.DebuggerConfigurationProperties", "type":
"boolean", "javaType": "boolean", "defaultValue": "false" },
{ "name": "camel.debug.waitForAttach", "description": "Whether the
debugger should suspend on startup, and wait for a remote debugger to attach.
This is what the IDEA and VSCode tooling is using.", "sourceType":
"org.apache.camel.main.DebuggerConfigurationProperties", "type": "boolean",
"javaType": "boolean", "defaultValue": "false" },
{ "name": "camel.faulttolerance.bulkheadEnabled", "description": "Whether
bulkhead is enabled or not on the circuit breaker. Default is false.",
"sourceType": "org.apache.camel.main.FaultToleranceConfigurationProperties",
"type": "boolean", "javaType": "java.lang.Boolean", "defaultValue": false },
{ "name": "camel.faulttolerance.bulkheadExecutorService", "description":
"References to a custom thread pool to use when bulkhead is enabled.",
"sourceType": "org.apache.camel.main.FaultToleranceConfigurationProperties",
"type": "string", "javaType": "java.lang.String" },
diff --git
a/components/camel-debug/src/main/java/org/apache/camel/component/debug/CamelDebuggerFactory.java
b/components/camel-debug/src/main/java/org/apache/camel/component/debug/CamelDebuggerFactory.java
index 6dd9e4bae11..f2842d56b60 100644
---
a/components/camel-debug/src/main/java/org/apache/camel/component/debug/CamelDebuggerFactory.java
+++
b/components/camel-debug/src/main/java/org/apache/camel/component/debug/CamelDebuggerFactory.java
@@ -37,7 +37,10 @@ public class CamelDebuggerFactory implements DebuggerFactory
{
camelContext.addLifecycleStrategy(new LifecycleStrategySupport() {
@Override
public void onContextStarted(CamelContext context) {
- backlog.enableDebugger();
+ // only enable debugger if not in standby mode
+ if (!backlog.isStandby()) {
+ backlog.enableDebugger();
+ }
}
@Override
diff --git a/core/camel-api/src/main/java/org/apache/camel/CamelContext.java
b/core/camel-api/src/main/java/org/apache/camel/CamelContext.java
index 041bb697acf..cbf1548e1dd 100644
--- a/core/camel-api/src/main/java/org/apache/camel/CamelContext.java
+++ b/core/camel-api/src/main/java/org/apache/camel/CamelContext.java
@@ -1180,6 +1180,18 @@ public interface CamelContext extends
CamelContextLifecycle, RuntimeConfiguratio
*/
boolean isBacklogTracingStandby();
+ /**
+ * Whether to set backlog debugger on standby. If on standby then the
backlog debugger is installed and made
+ * available. Then the backlog debugger can be enabled later at runtime
via JMX or via Java API.
+ */
+ void setDebugStandby(boolean debugStandby);
+
+ /**
+ * Whether to set backlog debugger on standby. If on standby then the
backlog debugger is installed and made
+ * available. Then the backlog debugger can be enabled later at runtime
via JMX or via Java API.
+ */
+ boolean isDebugStandby();
+
/**
* Whether backlog tracing should trace inner details from route templates
(or kamelets). Turning this off can
* reduce the verbosity of tracing when using many route templates, and
allow to focus on tracing your own Camel
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 284f33844fa..b8582c98f12 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
@@ -95,6 +95,22 @@ public interface BacklogDebugger extends StatefulService {
*/
boolean isEnabled();
+ /**
+ * Whether the debugger is standby.
+ * <p>
+ * If a debugger is in standby then the tracer is activated during startup
and are ready to be enabled manually via
+ * JMX or calling the enableDebugger method.
+ */
+ boolean isStandby();
+
+ /**
+ * Whether the debugger is standby.
+ * <p>
+ * If a debugger is in standby then the tracer is activated during startup
and are ready to be enabled manually via
+ * JMX or calling the enableDebugger method.
+ */
+ void setStandby(boolean standby);
+
/**
* Does the node have a breakpoint
*/
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 e37fccaecc5..8ccc3a2cc01 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
@@ -65,6 +65,7 @@ public final class DefaultBacklogDebugger extends
ServiceSupport implements Back
private LoggingLevel loggingLevel = LoggingLevel.INFO;
private final CamelLogger logger = new CamelLogger(LOG, loggingLevel);
private final AtomicBoolean enabled = new AtomicBoolean();
+ private final AtomicBoolean standby = new AtomicBoolean();
private final AtomicLong debugCounter = new AtomicLong();
private final Debugger debugger;
private final ConcurrentMap<String, NodeBreakpoint> breakpoints = new
ConcurrentHashMap<>();
@@ -138,7 +139,9 @@ public final class DefaultBacklogDebugger extends
ServiceSupport implements Back
// must enable message history for debugger to capture more details
context.setMessageHistory(true);
- return new DefaultBacklogDebugger(context, resolveSuspendMode());
+ DefaultBacklogDebugger answer = new DefaultBacklogDebugger(context,
resolveSuspendMode());
+ answer.setStandby(context.isDebugStandby());
+ return answer;
}
/**
@@ -199,6 +202,16 @@ public final class DefaultBacklogDebugger extends
ServiceSupport implements Back
return enabled.get();
}
+ @Override
+ public boolean isStandby() {
+ return standby.get();
+ }
+
+ @Override
+ public void setStandby(boolean standby) {
+ this.standby.set(standby);
+ }
+
@Override
public boolean hasBreakpoint(String nodeId) {
return breakpoints.containsKey(nodeId);
diff --git
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
index 2d2726ea1d2..e4e0b4f63b6 100644
---
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
+++
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
@@ -237,6 +237,7 @@ public abstract class AbstractCamelContext extends
BaseService
private String tracingLoggingFormat;
private Boolean modeline = Boolean.FALSE;
private Boolean debug = Boolean.FALSE;
+ private Boolean debugStandby = Boolean.FALSE;
private String debugBreakpoints;
private Boolean messageHistory = Boolean.FALSE;
private Boolean logMask = Boolean.FALSE;
@@ -1738,6 +1739,16 @@ public abstract class AbstractCamelContext extends
BaseService
return debug;
}
+ @Override
+ public void setDebugStandby(boolean debugStandby) {
+ this.debugStandby = debugStandby;
+ }
+
+ @Override
+ public boolean isDebugStandby() {
+ return debugStandby != null && debugStandby;
+ }
+
public void setDebuggingBreakpoints(String debugBreakpoints) {
this.debugBreakpoints = debugBreakpoints;
}
@@ -2254,7 +2265,7 @@ public abstract class AbstractCamelContext extends
BaseService
}
}
}
- if (!debuggerDetected && isDebugging()) {
+ if (!debuggerDetected && (isDebugging() || isDebugStandby())) {
// debugging enabled but camel-debug was not auto-detected from
classpath
// so install default debugger
BacklogDebugger backlog =
DefaultBacklogDebugger.createDebugger(this);
diff --git
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultChannel.java
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultChannel.java
index 84fb4e61f2a..07539ebedc0 100644
---
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultChannel.java
+++
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultChannel.java
@@ -174,7 +174,7 @@ public class DefaultChannel extends CamelInternalProcessor
implements Channel {
// then wrap the output with the tracer and debugger (debugger first,
// as we do not want regular tracer to trace the debugger)
- if (route.isDebugging()) {
+ if (camelContext.isDebugStandby() || route.isDebugging()) {
final Debugger customDebugger = camelContext.getDebugger();
if (customDebugger != null) {
// use custom debugger
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 6f6540ce673..72100c0295a 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
@@ -67,6 +67,7 @@ public class DebugDevConsole extends AbstractDevConsole {
if (backlog != null) {
sb.append("Settings:");
sb.append(String.format("\n Enabled: %s", backlog.isEnabled()));
+ sb.append(String.format("\n Standby: %s", backlog.isStandby()));
sb.append(String.format("\n Suspended Mode: %s",
backlog.isSuspendMode()));
sb.append(String.format("\n Fallback Timeout: %ss",
backlog.getFallbackTimeout())); // is in seconds
sb.append(String.format("\n Logging Level: %s",
backlog.getLoggingLevel()));
@@ -107,7 +108,11 @@ public class DebugDevConsole extends AbstractDevConsole {
return;
}
- if ("attach".equalsIgnoreCase(command)) {
+ if ("enable".equalsIgnoreCase(command)) {
+ backlog.enableDebugger();
+ } else if ("disable".equalsIgnoreCase(command)) {
+ backlog.disableDebugger();
+ } else if ("attach".equalsIgnoreCase(command)) {
backlog.attach();
} else if ("detach".equalsIgnoreCase(command)) {
backlog.detach();
@@ -147,6 +152,7 @@ public class DebugDevConsole extends AbstractDevConsole {
BacklogDebugger backlog =
getCamelContext().hasService(BacklogDebugger.class);
if (backlog != null) {
root.put("enabled", backlog.isEnabled());
+ root.put("standby", backlog.isStandby());
root.put("suspendedMode", backlog.isSuspendMode());
root.put("fallbackTimeout", backlog.getFallbackTimeout());
root.put("loggingLevel", backlog.getLoggingLevel());
diff --git
a/core/camel-core-engine/src/generated/java/org/apache/camel/impl/CamelContextConfigurer.java
b/core/camel-core-engine/src/generated/java/org/apache/camel/impl/CamelContextConfigurer.java
index 43067b7d8e7..36058f48b6b 100644
---
a/core/camel-core-engine/src/generated/java/org/apache/camel/impl/CamelContextConfigurer.java
+++
b/core/camel-core-engine/src/generated/java/org/apache/camel/impl/CamelContextConfigurer.java
@@ -39,6 +39,8 @@ public class CamelContextConfigurer extends
org.apache.camel.support.component.P
case "CaseInsensitiveHeaders":
target.setCaseInsensitiveHeaders(property(camelContext,
java.lang.Boolean.class, value)); return true;
case "classresolver":
case "ClassResolver": target.setClassResolver(property(camelContext,
org.apache.camel.spi.ClassResolver.class, value)); return true;
+ case "debugstandby":
+ case "DebugStandby": target.setDebugStandby(property(camelContext,
boolean.class, value)); return true;
case "debugger":
case "Debugger": target.setDebugger(property(camelContext,
org.apache.camel.spi.Debugger.class, value)); return true;
case "debugging":
@@ -158,6 +160,8 @@ public class CamelContextConfigurer extends
org.apache.camel.support.component.P
case "CaseInsensitiveHeaders": return java.lang.Boolean.class;
case "classresolver":
case "ClassResolver": return org.apache.camel.spi.ClassResolver.class;
+ case "debugstandby":
+ case "DebugStandby": return boolean.class;
case "debugger":
case "Debugger": return org.apache.camel.spi.Debugger.class;
case "debugging":
@@ -278,6 +282,8 @@ public class CamelContextConfigurer extends
org.apache.camel.support.component.P
case "CaseInsensitiveHeaders": return
target.isCaseInsensitiveHeaders();
case "classresolver":
case "ClassResolver": return target.getClassResolver();
+ case "debugstandby":
+ case "DebugStandby": return target.isDebugStandby();
case "debugger":
case "Debugger": return target.getDebugger();
case "debugging":
diff --git
a/core/camel-main/src/generated/java/org/apache/camel/main/DebuggerConfigurationPropertiesConfigurer.java
b/core/camel-main/src/generated/java/org/apache/camel/main/DebuggerConfigurationPropertiesConfigurer.java
index 811756e0a99..c9b2f6c3d92 100644
---
a/core/camel-main/src/generated/java/org/apache/camel/main/DebuggerConfigurationPropertiesConfigurer.java
+++
b/core/camel-main/src/generated/java/org/apache/camel/main/DebuggerConfigurationPropertiesConfigurer.java
@@ -41,6 +41,8 @@ public class DebuggerConfigurationPropertiesConfigurer
extends org.apache.camel.
case "LoggingLevel": target.setLoggingLevel(property(camelContext,
org.apache.camel.LoggingLevel.class, value)); return true;
case "singlestepincludestartend":
case "SingleStepIncludeStartEnd":
target.setSingleStepIncludeStartEnd(property(camelContext, boolean.class,
value)); return true;
+ case "standby":
+ case "Standby": target.setStandby(property(camelContext,
boolean.class, value)); return true;
case "waitforattach":
case "WaitForAttach": target.setWaitForAttach(property(camelContext,
boolean.class, value)); return true;
default: return false;
@@ -70,6 +72,8 @@ public class DebuggerConfigurationPropertiesConfigurer
extends org.apache.camel.
case "LoggingLevel": return org.apache.camel.LoggingLevel.class;
case "singlestepincludestartend":
case "SingleStepIncludeStartEnd": return boolean.class;
+ case "standby":
+ case "Standby": return boolean.class;
case "waitforattach":
case "WaitForAttach": return boolean.class;
default: return null;
@@ -100,6 +104,8 @@ public class DebuggerConfigurationPropertiesConfigurer
extends org.apache.camel.
case "LoggingLevel": return target.getLoggingLevel();
case "singlestepincludestartend":
case "SingleStepIncludeStartEnd": return
target.isSingleStepIncludeStartEnd();
+ case "standby":
+ case "Standby": return target.isStandby();
case "waitforattach":
case "WaitForAttach": return target.isWaitForAttach();
default: return null;
diff --git
a/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json
b/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json
index 8e56959bc3c..b5d6c587081 100644
---
a/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json
+++
b/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json
@@ -153,6 +153,7 @@
{ "name": "camel.debug.includeExchangeProperties", "description": "Whether
to include the exchange properties in the traced message", "sourceType":
"org.apache.camel.main.DebuggerConfigurationProperties", "type": "boolean",
"javaType": "boolean", "defaultValue": true },
{ "name": "camel.debug.loggingLevel", "description": "The debugger logging
level to use when logging activity.", "sourceType":
"org.apache.camel.main.DebuggerConfigurationProperties", "type": "object",
"javaType": "org.apache.camel.LoggingLevel", "defaultValue": "INFO", "enum": [
"ERROR", "WARN", "INFO", "DEBUG", "TRACE", "OFF" ] },
{ "name": "camel.debug.singleStepIncludeStartEnd", "description": "In
single step mode, then when the exchange is created and completed, then
simulate a breakpoint at start and end, that allows to suspend and watch the
incoming\/complete exchange at the route (you can see message body as response,
failed exception etc).", "sourceType":
"org.apache.camel.main.DebuggerConfigurationProperties", "type": "boolean",
"javaType": "boolean", "defaultValue": "false" },
+ { "name": "camel.debug.standby", "description": "To set the debugger in
standby mode, where the debugger will be installed by not automatic enabled.
The debugger can then later be enabled explicit from Java, JMX or tooling.",
"sourceType": "org.apache.camel.main.DebuggerConfigurationProperties", "type":
"boolean", "javaType": "boolean", "defaultValue": "false" },
{ "name": "camel.debug.waitForAttach", "description": "Whether the
debugger should suspend on startup, and wait for a remote debugger to attach.
This is what the IDEA and VSCode tooling is using.", "sourceType":
"org.apache.camel.main.DebuggerConfigurationProperties", "type": "boolean",
"javaType": "boolean", "defaultValue": "false" },
{ "name": "camel.faulttolerance.bulkheadEnabled", "description": "Whether
bulkhead is enabled or not on the circuit breaker. Default is false.",
"sourceType": "org.apache.camel.main.FaultToleranceConfigurationProperties",
"type": "boolean", "javaType": "java.lang.Boolean", "defaultValue": false },
{ "name": "camel.faulttolerance.bulkheadExecutorService", "description":
"References to a custom thread pool to use when bulkhead is enabled.",
"sourceType": "org.apache.camel.main.FaultToleranceConfigurationProperties",
"type": "string", "javaType": "java.lang.String" },
diff --git a/core/camel-main/src/main/docs/main.adoc
b/core/camel-main/src/main/docs/main.adoc
index 6fc77d2bfd6..beac1024996 100644
--- a/core/camel-main/src/main/docs/main.adoc
+++ b/core/camel-main/src/main/docs/main.adoc
@@ -174,7 +174,7 @@ The camel.server supports 11 options, which are listed
below.
=== Camel Debugger configurations
-The camel.debug supports 11 options, which are listed below.
+The camel.debug supports 12 options, which are listed below.
[width="100%",cols="2,5,^1,2",options="header"]
|===
@@ -189,6 +189,7 @@ The camel.debug supports 11 options, which are listed below.
| *camel.debug.includeExchange{zwsp}Properties* | Whether to include the
exchange properties in the traced message | true | boolean
| *camel.debug.loggingLevel* | The debugger logging level to use when logging
activity. | INFO | LoggingLevel
| *camel.debug.singleStepInclude{zwsp}StartEnd* | In single step mode, then
when the exchange is created and completed, then simulate a breakpoint at start
and end, that allows to suspend and watch the incoming/complete exchange at the
route (you can see message body as response, failed exception etc). | false |
boolean
+| *camel.debug.standby* | To set the debugger in standby mode, where the
debugger will be installed by not automatic enabled. The debugger can then
later be enabled explicit from Java, JMX or tooling. | false | boolean
| *camel.debug.waitForAttach* | Whether the debugger should suspend on
startup, and wait for a remote debugger to attach. This is what the IDEA and
VSCode tooling is using. | false | boolean
|===
diff --git
a/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java
b/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java
index 660fa08e5f6..e04d05609b9 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java
@@ -1561,7 +1561,7 @@ public abstract class BaseMainSupport extends BaseService
{
setPropertiesOnTarget(camelContext, config, properties, "camel.debug.",
failIfNotSet, true, autoConfiguredProperties);
- if (!config.isEnabled()) {
+ if (!config.isEnabled() && !config.isStandby()) {
return;
}
@@ -1569,9 +1569,11 @@ public abstract class BaseMainSupport extends
BaseService {
camelContext.setSourceLocationEnabled(true);
// enable debugger on camel
- camelContext.setDebugging(true);
+ camelContext.setDebugging(config.isEnabled());
+ camelContext.setDebugStandby(config.isStandby());
BacklogDebugger debugger =
DefaultBacklogDebugger.createDebugger(camelContext);
+ debugger.setStandby(config.isStandby());
debugger.setInitialBreakpoints(config.getBreakpoints());
debugger.setSingleStepIncludeStartEnd(config.isSingleStepIncludeStartEnd());
debugger.setBodyMaxChars(config.getBodyMaxChars());
@@ -1587,7 +1589,10 @@ public abstract class BaseMainSupport extends
BaseService {
camelContext.addLifecycleStrategy(new LifecycleStrategySupport() {
@Override
public void onContextStarted(CamelContext context) {
- debugger.enableDebugger();
+ // only enable debugger if not in standby mode
+ if (!debugger.isStandby()) {
+ debugger.enableDebugger();
+ }
}
@Override
diff --git
a/core/camel-main/src/main/java/org/apache/camel/main/DebuggerConfigurationProperties.java
b/core/camel-main/src/main/java/org/apache/camel/main/DebuggerConfigurationProperties.java
index de1113897e8..db62f28227b 100644
---
a/core/camel-main/src/main/java/org/apache/camel/main/DebuggerConfigurationProperties.java
+++
b/core/camel-main/src/main/java/org/apache/camel/main/DebuggerConfigurationProperties.java
@@ -31,6 +31,8 @@ public class DebuggerConfigurationProperties implements
BootstrapCloseable {
@Metadata
private boolean enabled;
+ @Metadata
+ private boolean standby;
@Metadata(label = "advanced")
private boolean waitForAttach;
@Metadata(defaultValue = "INFO")
@@ -76,6 +78,18 @@ public class DebuggerConfigurationProperties implements
BootstrapCloseable {
this.enabled = enabled;
}
+ public boolean isStandby() {
+ return standby;
+ }
+
+ /**
+ * To set the debugger in standby mode, where the debugger will be
installed by not automatic enabled. The debugger
+ * can then later be enabled explicit from Java, JMX or tooling.
+ */
+ public void setStandby(boolean standby) {
+ this.standby = standby;
+ }
+
public boolean isWaitForAttach() {
return waitForAttach;
}
@@ -202,6 +216,15 @@ public class DebuggerConfigurationProperties implements
BootstrapCloseable {
return (DebuggerConfigurationProperties) this;
}
+ /**
+ * To set the debugger in standby mode, where the debugger will be
installed by not automatic enabled. The debugger
+ * can then later be enabled explicit from Java, JMX or tooling.
+ */
+ public DebuggerConfigurationProperties withStandby(boolean standby) {
+ this.standby = standby;
+ return (DebuggerConfigurationProperties) this;
+ }
+
/**
* Whether the debugger should suspend on startup, and wait for a remote
debugger to attach. This is what the IDEA
* and VSCode tooling is using.
diff --git
a/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationConfigurer.java
b/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationConfigurer.java
index 3d958a06a0c..7b6f4bcedff 100644
---
a/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationConfigurer.java
+++
b/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationConfigurer.java
@@ -43,6 +43,7 @@ import org.apache.camel.model.Model;
import org.apache.camel.model.ModelCamelContext;
import org.apache.camel.model.ModelLifecycleStrategy;
import org.apache.camel.spi.AsyncProcessorAwaitManager;
+import org.apache.camel.spi.BacklogDebugger;
import org.apache.camel.spi.BeanIntrospection;
import org.apache.camel.spi.ClassResolver;
import org.apache.camel.spi.CliConnectorFactory;
@@ -395,6 +396,10 @@ public final class DefaultConfigurationConfigurer {
if (bt != null) {
camelContext.getCamelContextExtension().addContextPlugin(BacklogTracer.class,
bt);
}
+ BacklogDebugger bd = getSingleBeanOfType(registry,
BacklogDebugger.class);
+ if (bd != null) {
+
camelContext.getCamelContextExtension().addContextPlugin(BacklogDebugger.class,
bd);
+ }
InflightRepository ir = getSingleBeanOfType(registry,
InflightRepository.class);
if (ir != null) {
camelContext.setInflightRepository(ir);
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 1f77619f5d0..3a1dc32a26c 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
@@ -38,6 +38,9 @@ public interface ManagedBacklogDebuggerMBean {
@ManagedAttribute(description = "Is debugger enabled")
boolean isEnabled();
+ @ManagedAttribute(description = "Is debugger standby")
+ boolean isStandby();
+
@ManagedOperation(description = "Enable the debugger")
void enableDebugger();
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 a3a86690544..a89d53da607 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
@@ -88,6 +88,11 @@ public class ManagedBacklogDebugger implements
ManagedBacklogDebuggerMBean {
return backlogDebugger.isEnabled();
}
+ @Override
+ public boolean isStandby() {
+ return backlogDebugger.isStandby();
+ }
+
@Override
public void enableDebugger() {
backlogDebugger.enableDebugger();
diff --git
a/core/camel-management/src/test/java/org/apache/camel/management/BacklogDebuggerStandbyTest.java
b/core/camel-management/src/test/java/org/apache/camel/management/BacklogDebuggerStandbyTest.java
new file mode 100644
index 00000000000..a978657b658
--- /dev/null
+++
b/core/camel-management/src/test/java/org/apache/camel/management/BacklogDebuggerStandbyTest.java
@@ -0,0 +1,126 @@
+/*
+ * 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.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.impl.debugger.DefaultBacklogDebugger;
+import org.apache.camel.spi.BacklogDebugger;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.DisabledOnOs;
+import org.junit.jupiter.api.condition.OS;
+
+import static org.awaitility.Awaitility.await;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+@DisabledOnOs(OS.AIX)
+public class BacklogDebuggerStandbyTest extends ManagementTestSupport {
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testBacklogDebuggerStandby() throws Exception {
+ MBeanServer mbeanServer = getMBeanServer();
+ ObjectName on = new ObjectName(
+ "org.apache.camel:context=" + context.getManagementName() +
",type=tracer,name=BacklogDebugger");
+ assertNotNull(on);
+ mbeanServer.isRegistered(on);
+
+ Boolean enabled = (Boolean) mbeanServer.getAttribute(on, "Enabled");
+ assertEquals(Boolean.FALSE, enabled, "Should not be enabled");
+
+ Boolean standby = (Boolean) mbeanServer.getAttribute(on, "Standby");
+ assertEquals(Boolean.TRUE, standby, "Should be standby");
+
+ // enable debugger
+ mbeanServer.invoke(on, "enableDebugger", null, null);
+
+ enabled = (Boolean) mbeanServer.getAttribute(on, "Enabled");
+ assertEquals(Boolean.TRUE, enabled, "Should be enabled");
+
+ // add breakpoint at bar
+ mbeanServer.invoke(on, "addBreakpoint", new Object[] { "bar" }, new
String[] { "java.lang.String" });
+
+ MockEndpoint mock = getMockEndpoint("mock:result");
+ mock.expectedMessageCount(0);
+ mock.setSleepForEmptyTest(100);
+
+ template.sendBody("seda:start", "Hello World");
+
+ assertMockEndpointsSatisfied();
+
+ // wait for breakpoint at bar
+ await().atMost(1, TimeUnit.SECONDS).untilAsserted(() -> {
+ Set<String> suspended = (Set<String>) mbeanServer.invoke(on,
"suspendedBreakpointNodeIds", null, null);
+ assertNotNull(suspended);
+ assertEquals(1, suspended.size());
+ assertEquals("bar", suspended.iterator().next());
+ });
+
+ // the message should be ours
+ String xml = (String) mbeanServer.invoke(on,
"dumpTracedMessagesAsXml", new Object[] { "bar", false },
+ new String[] { "java.lang.String", "boolean" });
+ assertNotNull(xml);
+ log.info(xml);
+
+ assertTrue(xml.contains("Hello World"), "Should contain our body");
+ assertTrue(xml.contains("<toNode>bar</toNode>"), "Should contain bar
node");
+
+ resetMocks();
+ mock.expectedMessageCount(1);
+
+ // resume breakpoint
+ mbeanServer.invoke(on, "resumeBreakpoint", new Object[] { "bar" }, new
String[] { "java.lang.String" });
+
+ assertMockEndpointsSatisfied();
+
+ // and no suspended anymore
+ Set<String> nodes = (Set<String>) mbeanServer.invoke(on,
"suspendedBreakpointNodeIds", null, null);
+ assertNotNull(nodes);
+ assertEquals(0, nodes.size());
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ // set debugger in standby mode
+ BacklogDebugger bd =
DefaultBacklogDebugger.createDebugger(context);
+ bd.setStandby(true);
+ context.addService(bd);
+ context.setDebugging(true);
+
+ from("seda:start?concurrentConsumers=2")
+ .setProperty("myProperty",
constant("myValue")).id("setProp")
+ .to("log:foo").id("foo")
+ .to("log:bar").id("bar")
+ .transform().constant("Bye World").id("transform")
+ .to("log:cheese?showExchangeId=true").id("cheese")
+ .to("mock:result").id("result");
+ }
+ };
+ }
+
+}
diff --git
a/core/camel-management/src/test/java/org/apache/camel/management/BacklogDebuggerTest.java
b/core/camel-management/src/test/java/org/apache/camel/management/BacklogDebuggerTest.java
index cbd75bbc775..3d81881d01d 100644
---
a/core/camel-management/src/test/java/org/apache/camel/management/BacklogDebuggerTest.java
+++
b/core/camel-management/src/test/java/org/apache/camel/management/BacklogDebuggerTest.java
@@ -53,6 +53,9 @@ public class BacklogDebuggerTest extends
ManagementTestSupport {
Boolean enabled = (Boolean) mbeanServer.getAttribute(on, "Enabled");
assertEquals(Boolean.FALSE, enabled, "Should not be enabled");
+ Boolean standby = (Boolean) mbeanServer.getAttribute(on, "Standby");
+ assertEquals(Boolean.FALSE, standby, "Should not be standby");
+
// enable debugger
mbeanServer.invoke(on, "enableDebugger", null, null);