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/12 10:48:48 UTC
(camel) branch main updated: CAMEL-22322: camel-jbang - camel debug for spring boot (#18874)
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 70adba06d72 CAMEL-22322: camel-jbang - camel debug for spring boot (#18874)
70adba06d72 is described below
commit 70adba06d726f6d48e0dfcc04a8cedd241d83760
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Tue Aug 12 12:48:43 2025 +0200
CAMEL-22322: camel-jbang - camel debug for spring boot (#18874)
---
.../java/org/apache/camel/spi/BacklogDebugger.java | 9 +-
.../org/apache/camel/resource-resolver/source | 2 +
.../impl/debugger/DefaultBacklogDebugger.java | 5 +
.../camel/impl/engine/AbstractCamelContext.java | 22 +--
.../impl/engine/DefaultResourceResolvers.java | 47 +++++
.../org/apache/camel/util/ResourceLoaderTest.java | 17 ++
.../org/apache/camel/main/BaseMainSupport.java | 57 +------
.../camel/main/DefaultConfigurationConfigurer.java | 68 ++++++++
.../apache/camel/main/DefaultRoutesCollector.java | 12 ++
.../camel/dsl/jbang/core/commands/Debug.java | 189 +++++++++++++++++++--
.../apache/camel/dsl/jbang/core/commands/Run.java | 6 +-
11 files changed, 347 insertions(+), 87 deletions(-)
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 027052f04cf..a660b43c5e1 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
@@ -81,15 +81,20 @@ public interface BacklogDebugger extends StatefulService {
void setLoggingLevel(String level);
/**
- * To enable the debugger
+ * To enable and start the debugger
*/
void enableDebugger();
/**
- * To disable the debugger
+ * To disable and stop the debugger
*/
void disableDebugger();
+ /**
+ * To configure whether the debugger should be enabled
+ */
+ void setEnabled(boolean enabled);
+
/**
* Whether the debugger is enabled
*/
diff --git a/core/camel-base-engine/src/generated/resources/META-INF/services/org/apache/camel/resource-resolver/source b/core/camel-base-engine/src/generated/resources/META-INF/services/org/apache/camel/resource-resolver/source
new file mode 100644
index 00000000000..ad600b90740
--- /dev/null
+++ b/core/camel-base-engine/src/generated/resources/META-INF/services/org/apache/camel/resource-resolver/source
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.impl.engine.DefaultResourceResolvers$SourceResolver
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 733f7791e7d..4011f60aa16 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
@@ -206,6 +206,11 @@ public final class DefaultBacklogDebugger extends ServiceSupport implements Back
clearBreakpoints();
}
+ @Override
+ public void setEnabled(boolean enabled) {
+ this.enabled.set(enabled);
+ }
+
@Override
public boolean isEnabled() {
return enabled.get();
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 9efb702c5de..dc2f9462082 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
@@ -2445,17 +2445,6 @@ public abstract class AbstractCamelContext extends BaseService
forceLazyInitialization();
- // setup cli-connector if not already done
- if (hasService(CliConnector.class) == null) {
- CliConnectorFactory ccf = getCamelContextExtension().getContextPlugin(CliConnectorFactory.class);
- if (ccf != null && ccf.isEnabled()) {
- CliConnector connector = ccf.createConnector();
- addService(connector, true);
- // force start cli connector early as otherwise it will be deferred until context is started
- // but, we want status available during startup phase
- ServiceHelper.startService(connector);
- }
- }
// auto-detect camel-debug on classpath (if debugger has not been explicit added)
boolean debuggerDetected = false;
if (getDebugger() == null && hasService(BacklogDebugger.class) == null) {
@@ -2480,6 +2469,17 @@ public abstract class AbstractCamelContext extends BaseService
addService(backlog, true, true);
}
}
+ // setup cli-connector if not already done (after debugger)
+ if (hasService(CliConnector.class) == null) {
+ CliConnectorFactory ccf = getCamelContextExtension().getContextPlugin(CliConnectorFactory.class);
+ if (ccf != null && ccf.isEnabled()) {
+ CliConnector connector = ccf.createConnector();
+ addService(connector, true);
+ // force start cli connector early as otherwise it will be deferred until context is started
+ // but, we want status available during startup phase
+ ServiceHelper.startService(connector);
+ }
+ }
addService(getManagementStrategy(), false);
diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultResourceResolvers.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultResourceResolvers.java
index 01dd83eec05..f72e9d0ad93 100644
--- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultResourceResolvers.java
+++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultResourceResolvers.java
@@ -287,6 +287,53 @@ public final class DefaultResourceResolvers {
}
}
+ /**
+ * An implementation of the {@link ResourceResolver} that resolves a {@link Resource} from file system in
+ * src/main/java.
+ */
+ @ResourceResolver(SourceResolver.SCHEME)
+ public static class SourceResolver extends ResourceResolverSupport {
+ public static final String SCHEME = "source";
+
+ public SourceResolver() {
+ super(SCHEME);
+ }
+
+ @Override
+ public Resource createResource(String location, String remaining) {
+ String dir = "src/main/java/";
+ boolean test = remaining.endsWith("?test=true");
+ if (test) {
+ remaining = remaining.substring(0, remaining.length() - 10);
+ dir = "src/test/java/";
+ }
+ String name = remaining.replace('.', '/') + ".java";
+ final File path = new File(getPath(dir + name));
+ return new ResourceSupport(SCHEME, location) {
+ @Override
+ public boolean exists() {
+ return path.exists();
+ }
+
+ @Override
+ public URI getURI() {
+ return path.toURI();
+ }
+
+ @Override
+ public InputStream getInputStream() throws IOException {
+ if (!exists()) {
+ throw new FileNotFoundException(path + " does not exist");
+ }
+ if (path.isDirectory()) {
+ throw new FileNotFoundException(path + " is a directory");
+ }
+ return new FileInputStream(path);
+ }
+ };
+ }
+ }
+
static final class HttpResource extends ResourceSupport implements ContentTypeAware {
private String contentType;
diff --git a/core/camel-core/src/test/java/org/apache/camel/util/ResourceLoaderTest.java b/core/camel-core/src/test/java/org/apache/camel/util/ResourceLoaderTest.java
index 293b7474658..559e96c8fce 100644
--- a/core/camel-core/src/test/java/org/apache/camel/util/ResourceLoaderTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/util/ResourceLoaderTest.java
@@ -26,6 +26,7 @@ import java.util.Base64;
import java.util.concurrent.atomic.AtomicReference;
import java.util.zip.GZIPOutputStream;
+import org.apache.camel.MyFoo;
import org.apache.camel.TestSupport;
import org.apache.camel.impl.DefaultCamelContext;
import org.apache.camel.impl.engine.DefaultResourceLoader;
@@ -339,4 +340,20 @@ public class ResourceLoaderTest extends TestSupport {
assertEquals(raw, content);
}
}
+
+ @Test
+ public void testLoadSource() throws Exception {
+ DefaultCamelContext context = new DefaultCamelContext();
+ Resource resource
+ = PluginHelper.getResourceLoader(context).resolveResource("source:" + MyFoo.class.getName() + "?test=true");
+
+ try (InputStream is = resource.getInputStream()) {
+ assertNotNull(is);
+
+ String content = context.getTypeConverter().convertTo(String.class, is);
+ assertNotNull(content);
+ assertTrue(content.contains("public class MyFoo {"));
+ }
+ }
+
}
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 f81857115c0..cff1264bd25 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
@@ -58,13 +58,10 @@ import org.apache.camel.console.DevConsoleRegistry;
import org.apache.camel.health.HealthCheck;
import org.apache.camel.health.HealthCheckRegistry;
import org.apache.camel.health.HealthCheckRepository;
-import org.apache.camel.impl.debugger.DebuggerJmxConnectorService;
-import org.apache.camel.impl.debugger.DefaultBacklogDebugger;
import org.apache.camel.impl.engine.DefaultCompileStrategy;
import org.apache.camel.impl.engine.DefaultRoutesLoader;
import org.apache.camel.saga.CamelSagaService;
import org.apache.camel.spi.AutowiredLifecycleStrategy;
-import org.apache.camel.spi.BacklogDebugger;
import org.apache.camel.spi.BacklogTracer;
import org.apache.camel.spi.CamelBeanPostProcessor;
import org.apache.camel.spi.CamelEvent;
@@ -2100,58 +2097,8 @@ public abstract class BaseMainSupport extends BaseService {
setPropertiesOnTarget(camelContext, config, properties, "camel.debug.",
failIfNotSet, true, autoConfiguredProperties);
- if (!config.isEnabled() && !config.isStandby()) {
- return;
- }
-
- // must enable source location and history
- // so debugger tooling knows to map breakpoints to source code
- camelContext.setSourceLocationEnabled(true);
- camelContext.setMessageHistory(true);
-
- // enable debugger on camel
- 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());
- debugger.setBodyIncludeStreams(config.isBodyIncludeStreams());
- debugger.setBodyIncludeFiles(config.isBodyIncludeFiles());
- debugger.setIncludeExchangeProperties(config.isIncludeExchangeProperties());
- debugger.setIncludeExchangeVariables(config.isIncludeExchangeVariables());
- debugger.setIncludeException(config.isIncludeException());
- debugger.setLoggingLevel(config.getLoggingLevel().name());
- debugger.setSuspendMode(config.isWaitForAttach()); // this option is named wait-for-attach
- debugger.setFallbackTimeout(config.getFallbackTimeout());
-
- // enable jmx connector if port is set
- if (config.isJmxConnectorEnabled()) {
- DebuggerJmxConnectorService connector = new DebuggerJmxConnectorService();
- connector.setCreateConnector(true);
- connector.setRegistryPort(config.getJmxConnectorPort());
- camelContext.addService(connector);
- }
-
- // start debugger after context is started
- camelContext.addLifecycleStrategy(new LifecycleStrategySupport() {
- @Override
- public void onContextStarted(CamelContext context) {
- // only enable debugger if not in standby mode
- if (!debugger.isStandby()) {
- debugger.enableDebugger();
- }
- }
-
- @Override
- public void onContextStopping(CamelContext context) {
- debugger.disableDebugger();
- }
- });
-
- camelContext.addService(debugger);
+ // use common logic to configure debugger
+ DefaultConfigurationConfigurer.configureBacklogDebugger(camelContext, config);
}
private void setTracerProperties(
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 e9e994d41f7..dd459d3a4af 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
@@ -36,6 +36,8 @@ import org.apache.camel.console.DevConsoleRegistry;
import org.apache.camel.health.HealthCheckRegistry;
import org.apache.camel.health.HealthCheckRepository;
import org.apache.camel.impl.debugger.BacklogTracer;
+import org.apache.camel.impl.debugger.DebuggerJmxConnectorService;
+import org.apache.camel.impl.debugger.DefaultBacklogDebugger;
import org.apache.camel.impl.engine.DefaultCompileStrategy;
import org.apache.camel.impl.engine.PooledExchangeFactory;
import org.apache.camel.impl.engine.PooledProcessorExchangeFactory;
@@ -91,6 +93,7 @@ import org.apache.camel.spi.VariableRepositoryFactory;
import org.apache.camel.support.ClassicUuidGenerator;
import org.apache.camel.support.DefaultContextReloadStrategy;
import org.apache.camel.support.DefaultUuidGenerator;
+import org.apache.camel.support.LifecycleStrategySupport;
import org.apache.camel.support.OffUuidGenerator;
import org.apache.camel.support.PluginHelper;
import org.apache.camel.support.RouteWatcherReloadStrategy;
@@ -664,6 +667,71 @@ public final class DefaultConfigurationConfigurer {
}
}
+ /**
+ * Configures the {@link BacklogDebugger} with the configuration.
+ *
+ * @param camelContext the camel context
+ * @param config the configuration
+ */
+ public static void configureBacklogDebugger(CamelContext camelContext, DebuggerConfigurationProperties config)
+ throws Exception {
+ if (!config.isEnabled() && !config.isStandby()) {
+ return;
+ }
+
+ // must enable source location and history
+ // so debugger tooling knows to map breakpoints to source code
+ camelContext.setSourceLocationEnabled(true);
+ camelContext.setMessageHistory(true);
+
+ // enable debugger on camel
+ camelContext.setDebugging(config.isEnabled());
+ camelContext.setDebugStandby(config.isStandby());
+
+ BacklogDebugger debugger = DefaultBacklogDebugger.createDebugger(camelContext);
+ debugger.setEnabled(config.isEnabled());
+ debugger.setStandby(config.isStandby());
+ debugger.setInitialBreakpoints(config.getBreakpoints());
+ debugger.setSingleStepIncludeStartEnd(config.isSingleStepIncludeStartEnd());
+ debugger.setBodyMaxChars(config.getBodyMaxChars());
+ debugger.setBodyIncludeStreams(config.isBodyIncludeStreams());
+ debugger.setBodyIncludeFiles(config.isBodyIncludeFiles());
+ debugger.setIncludeExchangeProperties(config.isIncludeExchangeProperties());
+ debugger.setIncludeExchangeVariables(config.isIncludeExchangeVariables());
+ debugger.setIncludeException(config.isIncludeException());
+ debugger.setLoggingLevel(config.getLoggingLevel().name());
+ debugger.setSuspendMode(config.isWaitForAttach()); // this option is named wait-for-attach
+ debugger.setFallbackTimeout(config.getFallbackTimeout());
+
+ // enable jmx connector if port is set
+ if (config.isJmxConnectorEnabled()) {
+ DebuggerJmxConnectorService connector = new DebuggerJmxConnectorService();
+ connector.setCreateConnector(true);
+ connector.setRegistryPort(config.getJmxConnectorPort());
+ camelContext.addService(connector);
+ }
+
+ // start debugger after context is started
+ camelContext.addLifecycleStrategy(new LifecycleStrategySupport() {
+ @Override
+ public void onContextStarted(CamelContext context) {
+ // only enable debugger if not in standby mode
+ if (debugger.isEnabled() && !debugger.isStandby()) {
+ debugger.enableDebugger();
+ }
+ }
+
+ @Override
+ public void onContextStopping(CamelContext context) {
+ if (debugger.isEnabled()) {
+ debugger.disableDebugger();
+ }
+ }
+ });
+
+ camelContext.addService(debugger);
+ }
+
/**
* Configures security vaults refresh such as AWS, Azure, Google.
*/
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/DefaultRoutesCollector.java b/core/camel-main/src/main/java/org/apache/camel/main/DefaultRoutesCollector.java
index 2a93cddcc03..a490f9f913e 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/DefaultRoutesCollector.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/DefaultRoutesCollector.java
@@ -29,8 +29,10 @@ import org.apache.camel.builder.LambdaRouteBuilder;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.spi.PackageScanResourceResolver;
import org.apache.camel.spi.Resource;
+import org.apache.camel.spi.ResourceAware;
import org.apache.camel.spi.RoutesLoader;
import org.apache.camel.support.PluginHelper;
+import org.apache.camel.support.ResourceHelper;
import org.apache.camel.util.AntPathMatcher;
import org.apache.camel.util.ObjectHelper;
import org.apache.camel.util.StopWatch;
@@ -143,6 +145,16 @@ public class DefaultRoutesCollector implements RoutesCollector {
}
}
+ // the route may have source code available so attempt to load as resource
+ for (RoutesBuilder route : routes) {
+ if (route instanceof ResourceAware ra && ra.getResource() == null) {
+ Resource r = ResourceHelper.resolveResource(camelContext, "source:" + route.getClass().getName());
+ if (r != null && r.exists()) {
+ ra.setResource(r);
+ }
+ }
+ }
+
return routes;
}
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 e53ee102704..dc07f0d36cc 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
@@ -18,18 +18,25 @@ package org.apache.camel.dsl.jbang.core.commands;
import java.io.BufferedReader;
import java.io.Console;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
+import java.io.Reader;
import java.io.StringWriter;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
+import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.AtomicReference;
import org.apache.camel.dsl.jbang.core.commands.action.MessageTableHelper;
import org.apache.camel.dsl.jbang.core.common.CamelCommandHelper;
@@ -46,11 +53,22 @@ import org.apache.camel.util.concurrent.ThreadHelper;
import org.apache.camel.util.json.JsonArray;
import org.apache.camel.util.json.JsonObject;
import org.apache.camel.util.json.Jsoner;
+import org.apache.maven.model.Activation;
+import org.apache.maven.model.Build;
+import org.apache.maven.model.Dependency;
+import org.apache.maven.model.Model;
+import org.apache.maven.model.Plugin;
+import org.apache.maven.model.PluginExecution;
+import org.apache.maven.model.Profile;
+import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
+import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
+import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.fusesource.jansi.Ansi;
import org.fusesource.jansi.AnsiConsole;
import picocli.CommandLine;
import picocli.CommandLine.Command;
+import static org.apache.camel.dsl.jbang.core.common.CommandLineHelper.CAMEL_JBANG_WORK_DIR;
import static org.apache.camel.util.IOHelper.buffered;
@Command(name = "debug", description = "Debug local Camel integration", sortOptions = false, showDefaultValues = true)
@@ -172,8 +190,14 @@ public class Debug extends Run {
printer().println(line);
}
// and any error
- String text = IOHelper.loadText(spawnError);
- printer().println(text);
+ if (spawnError != null) {
+ try {
+ String text = IOHelper.loadText(spawnError);
+ printer().println(text);
+ } catch (Exception e) {
+ // ignore
+ }
+ }
return -1;
}
} while (exit == 0 && !quit.get());
@@ -183,23 +207,25 @@ public class Debug extends Run {
private void doReadLog(AtomicBoolean quit) {
do {
- InputStreamReader isr = new InputStreamReader(spawnOutput);
- try {
- BufferedReader reader = buffered(isr);
- while (true) {
- String line = reader.readLine();
- if (line != null) {
- while (logBuffer.size() >= 100) {
- logBuffer.remove(0);
+ if (spawnOutput != null) {
+ InputStreamReader isr = new InputStreamReader(spawnOutput);
+ try {
+ BufferedReader reader = buffered(isr);
+ while (true) {
+ String line = reader.readLine();
+ if (line != null) {
+ while (logBuffer.size() >= 100) {
+ logBuffer.remove(0);
+ }
+ logBuffer.add(line);
+ logUpdated.set(true);
+ } else {
+ break;
}
- logBuffer.add(line);
- logUpdated.set(true);
- } else {
- break;
}
+ } catch (Exception e) {
+ // ignore
}
- } catch (Exception e) {
- // ignore
}
} while (!quit.get());
}
@@ -237,6 +263,137 @@ public class Debug extends Run {
@Override
protected int runDebug(KameletMain main) throws Exception {
+ // is this a maven project
+ File pom = new File("pom.xml");
+ if (pom.isFile() && pom.exists()) {
+ // is this a spring-boot project
+ try (InputStream is = new FileInputStream(pom)) {
+ String text = IOHelper.loadText(is);
+ if (text.contains("camel-spring-boot-bom")) {
+ return doRunDebugSpringBoot(main);
+ }
+ }
+ }
+ return doRunDebug(main);
+ }
+
+ private int doRunDebugSpringBoot(KameletMain main) throws Exception {
+ Path pom = Paths.get("pom.xml");
+ MavenXpp3Reader mavenReader = new MavenXpp3Reader();
+ try (Reader reader = Files.newBufferedReader(pom)) {
+ Model model = mavenReader.read(reader);
+
+ // include camel-debug dependency
+ Dependency d = new Dependency();
+ d.setGroupId("org.apache.camel.springboot");
+ d.setArtifactId("camel-debug-starter");
+ model.getDependencies().add(d);
+ d = new Dependency();
+ d.setGroupId("org.apache.camel.springboot");
+ d.setArtifactId("camel-cli-connector-starter");
+ model.getDependencies().add(d);
+
+ Profile mp = new Profile();
+ model.addProfile(mp);
+ mp.setId("camel-debug");
+ Activation a = new Activation();
+ a.setActiveByDefault(true);
+ mp.setActivation(a);
+
+ Build b = new Build();
+ mp.setBuild(b);
+
+ Plugin pi = new Plugin();
+ b.addPlugin(pi);
+ pi.setGroupId("org.springframework.boot");
+ pi.setArtifactId("spring-boot-maven-plugin");
+ pi.setVersion("${spring-boot-version}");
+ PluginExecution pe = new PluginExecution();
+ pe.addGoal("repackage");
+ pi.addExecution(pe);
+ Xpp3Dom cfg = new Xpp3Dom("finalName");
+ cfg.setValue("camel-jbang-debug");
+ Xpp3Dom root = new Xpp3Dom("configuration");
+ root.addChild(cfg);
+ pi.setConfiguration(root);
+
+ MavenXpp3Writer w = new MavenXpp3Writer();
+ FileOutputStream fos = new FileOutputStream("camel-jbang-debug-pom.xml", false);
+ w.write(fos, model);
+ IOHelper.close(fos);
+
+ printer().println("Preparing Camel Spring Boot for debugging ...");
+
+ // use maven wrapper if present
+ String mvnw = "/mvnw";
+ if (FileUtil.isWindows()) {
+ mvnw = "/mvnw.cmd";
+ }
+ if (!new File(mvnw).exists()) {
+ mvnw = "mvn";
+ }
+ // use maven to build the JAR and then run the JAR after-wards
+ ProcessBuilder pb = new ProcessBuilder();
+ pb.command(mvnw, "-Dmaven.test.skip", "--file", "camel-jbang-debug-pom.xml", "package", "spring-boot:repackage");
+ Process p = pb.start();
+
+ if (p.waitFor(30, TimeUnit.SECONDS)) {
+ AtomicReference<Process> processRef = new AtomicReference<>();
+ Runtime.getRuntime().addShutdownHook(new Thread(() -> {
+ try {
+ // We need to wait for the process to exit before doing any cleanup
+ Process process = processRef.get();
+ if (process != null) {
+ process.destroy();
+ for (int i = 0; i < 30; i++) {
+ if (!process.isAlive()) {
+ break;
+ }
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+ removeDir(Paths.get(RUN_PLATFORM_DIR));
+ removeDir(Paths.get(CAMEL_JBANG_WORK_DIR));
+ Files.deleteIfExists(Paths.get("camel-jbang-debug-pom.xml"));
+ } catch (Exception e) {
+ // Ignore
+ }
+ }));
+
+ // okay build is complete then run java
+ pb = new ProcessBuilder();
+ pb.command("java",
+ "-Dcamel.debug.enabled=true",
+ (breakpoint == null
+ ? "-Dcamel.debug.breakpoints=_all_routes_" : "-Dcamel.debug.breakpoints=" + breakpoint),
+ "-Dcamel.debug.loggingLevel=DEBUG",
+ "-Dcamel.debug.singleStepIncludeStartEnd=true",
+ loggingColor ? "-Dspring.output.ansi.enabled=ALWAYS" : "-Dspring.output.ansi.enabled=NEVER",
+ "-jar", "target/camel-jbang-debug.jar");
+
+ p = pb.start();
+ processRef.set(p);
+ this.spawnOutput = p.getInputStream();
+ this.spawnError = p.getErrorStream();
+ this.spawnPid = p.pid();
+ printer().println("Debugging Camel Spring Boot integration: " + name + " with PID: " + p.pid());
+ } else {
+ printer().printErr("Timed out preparing Camel Spring Boot for debugging");
+ this.spawnError = p.getErrorStream();
+ this.spawnPid = p.pid();
+ p.destroy();
+ return -1;
+ }
+ }
+
+ return 0;
+ }
+
+ protected int doRunDebug(KameletMain main) throws Exception {
List<String> cmds = new ArrayList<>(spec.commandLine().getParseResult().originalArgs());
// debug should be run
diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
index ea5c63e702c..fa3a84dd8bc 100644
--- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
+++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
@@ -87,7 +87,7 @@ public class Run extends CamelCommand {
public static final String RUN_JAVA_SH = "classpath:templates/run-java.sh";
public static final String RUN_SETTINGS_FILE = "camel-jbang-run.properties";
- private static final String RUN_PLATFORM_DIR = ".camel-jbang-run";
+ public static final String RUN_PLATFORM_DIR = ".camel-jbang-run";
private static final String[] ACCEPTED_XML_ROOT_ELEMENT_NAMES = new String[] {
"route", "routes",
@@ -1228,7 +1228,7 @@ public class Run extends CamelCommand {
if (FileUtil.isWindows()) {
mvnw = "/mvnw.cmd";
}
- pb.command(runDirPath.toString() + mvnw, "--quiet", "--file",
+ pb.command(runDirPath + mvnw, "--quiet", "--file",
runDirPath.toRealPath().resolve("pom.xml").toString(),
"spring-boot:run");
@@ -2013,7 +2013,7 @@ public class Run extends CamelCommand {
}
}
- private static void removeDir(Path directory) {
+ protected static void removeDir(Path directory) {
try {
if (Files.exists(directory)) {
Files.walk(directory)