Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
Spring Boot auto-configuration for the Camel Debugger.

This starter enables the Camel Debugger in your Spring Boot application, allowing you to set breakpoints and step through Camel routes during development. The debugger integrates with IDEs and tooling through JMX.
This starter enables the Camel Debugger in your Spring Boot application, allowing you to set breakpoints and step through Camel routes during development. The debugger is controlled from Java, JMX or tooling, and can additionally expose a JMX RMI connector for remote tooling, which is disabled by default.
20 changes: 20 additions & 0 deletions components-starter/camel-debug-starter/src/main/doc/usage.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
Adding this starter to the classpath installs and enables the Camel Debugger. The debugger can be turned off with:

[source,properties]
----
camel.debug.enabled = false
----

=== JMX connector

Tooling that attaches to the debugger from another process, such as the IntelliJ IDEA and VS Code Camel plugins, uses a JMX RMI connector. The connector is *disabled by default*, so having this starter on the classpath never opens a listening socket on its own. Enable it explicitly when remote tooling needs to attach:

[source,properties]
----
camel.debug.jmx-connector-enabled = true
camel.debug.jmx-connector-port = 1099
----

WARNING: The JMX RMI connector is created without authentication or transport security. Anyone able to reach the port can control the debugger, suspend routes and read message payloads. Only enable it on a trusted network, and make sure the port is bound to a loopback interface or protected by a firewall.

The `camel debug` command of Camel JBang does not need this connector: it drives a Spring Boot application through the local CLI connector provided by `camel-cli-connector-starter`.
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,14 @@
{
"name": "camel.debug.jmx-connector-enabled",
"type": "java.lang.Boolean",
"description": "Whether to create JMX connector that allows tooling to control the Camel debugger. This is what the IDEA and VSCode tooling is using.",
"description": "Whether to create JMX connector that allows tooling to control the Camel debugger. This is what the IDEA and VSCode tooling is using. The connector opens an RMI registry and a JMX RMI server on the configured port, without authentication or transport security, so it is disabled by default and must be turned on explicitly. Only enable it on a trusted network, and bind or firewall the port accordingly.",
"sourceType": "org.apache.camel.spring.boot.debug.CamelDebugConfigurationProperties",
"defaultValue": true
"defaultValue": false
},
{
"name": "camel.debug.jmx-connector-port",
"type": "java.lang.Integer",
"description": "Port number to expose a JMX RMI connector for tooling that needs to control the debugger.",
"description": "Port number to expose a JMX RMI connector for tooling that needs to control the debugger. Only in use when the JMX connector is enabled.",
"sourceType": "org.apache.camel.spring.boot.debug.CamelDebugConfigurationProperties",
"defaultValue": 1099
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,14 +101,17 @@ public class CamelDebugConfigurationProperties {
private long fallbackTimeout = 300;

/**
* Whether to create JMX connector that allows tooling to control the Camel debugger.
* This is what the IDEA and VSCode tooling is using.
* Whether to create JMX connector that allows tooling to control the Camel debugger. This is what the IDEA and
* VSCode tooling is using. The connector opens an RMI registry and a JMX RMI server on the configured port, without
* authentication or transport security, so it is disabled by default and must be turned on explicitly. Only enable
* it on a trusted network, and bind or firewall the port accordingly.
*/
@Metadata(label = "advanced", defaultValue = "true")
private boolean jmxConnectorEnabled = true;
@Metadata(label = "advanced", defaultValue = "false")
private boolean jmxConnectorEnabled;

/**
* Port number to expose a JMX RMI connector for tooling that needs to control the debugger.
* Port number to expose a JMX RMI connector for tooling that needs to control the debugger. Only in use when the
* JMX connector is enabled.
*/
@Metadata(label = "advanced", defaultValue = "1099")
private int jmxConnectorPort = 1099;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* 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.spring.boot.debug;

import org.apache.camel.CamelContext;
import org.apache.camel.impl.debugger.DebuggerJmxConnectorService;
import org.apache.camel.main.DebuggerConfigurationProperties;
import org.apache.camel.spi.BacklogDebugger;
import org.apache.camel.spring.boot.CamelAutoConfiguration;
import org.apache.camel.test.spring.junit6.CamelSpringBootTest;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.annotation.DirtiesContext;

import static org.assertj.core.api.Assertions.assertThat;

/**
* The debugger itself is installed when the starter is on the classpath, but the JMX RMI connector it can expose is
* opt-in, so no socket is opened by default.
*/
@DirtiesContext
@CamelSpringBootTest
@EnableAutoConfiguration
@SpringBootTest(classes = {
CamelDebugAutoConfigurationDefaultTest.TestConfiguration.class,
CamelDebugAutoConfiguration.class,
CamelAutoConfiguration.class
})
class CamelDebugAutoConfigurationDefaultTest {

@Autowired
CamelContext camelContext;

@Autowired
CamelDebugConfigurationProperties configurationProperties;

@Autowired
DebuggerConfigurationProperties debuggerConfigurationProperties;

@Test
void shouldEnableTheDebuggerByDefault() {
assertThat(configurationProperties.isEnabled()).isTrue();
assertThat(debuggerConfigurationProperties.isEnabled()).isTrue();
assertThat(camelContext.hasService(BacklogDebugger.class)).isNotNull();
}

@Test
void shouldNotEnableTheJmxConnectorByDefault() {
assertThat(configurationProperties.isJmxConnectorEnabled()).isFalse();
assertThat(debuggerConfigurationProperties.isJmxConnectorEnabled()).isFalse();
}

@Test
void shouldNotStartAnyJmxConnectorServiceByDefault() {
assertThat(camelContext.hasService(DebuggerJmxConnectorService.class)).isNull();
}

@Configuration
static class TestConfiguration {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* 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.spring.boot.debug;

import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.concurrent.TimeUnit;

import org.apache.camel.CamelContext;
import org.apache.camel.impl.debugger.DebuggerJmxConnectorService;
import org.apache.camel.main.DebuggerConfigurationProperties;
import org.apache.camel.spring.boot.CamelAutoConfiguration;
import org.apache.camel.test.AvailablePortFinder;
import org.apache.camel.test.spring.junit6.CamelSpringBootTest;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;

import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;

/**
* The JMX RMI connector is opened only when it is explicitly requested.
*/
@DirtiesContext
@CamelSpringBootTest
@EnableAutoConfiguration
@SpringBootTest(classes = {
CamelDebugAutoConfigurationJmxConnectorTest.TestConfiguration.class,
CamelDebugAutoConfiguration.class,
CamelAutoConfiguration.class
})
class CamelDebugAutoConfigurationJmxConnectorTest {

private static final int PORT = AvailablePortFinder.getNextAvailable();

@Autowired
CamelContext camelContext;

@Autowired
DebuggerConfigurationProperties debuggerConfigurationProperties;

@DynamicPropertySource
static void debugProperties(DynamicPropertyRegistry registry) {
registry.add("camel.debug.jmx-connector-enabled", () -> "true");
registry.add("camel.debug.jmx-connector-port", () -> PORT);
}

@Test
void shouldStartTheJmxConnectorWhenEnabled() {
assertThat(debuggerConfigurationProperties.isJmxConnectorEnabled()).isTrue();
assertThat(debuggerConfigurationProperties.getJmxConnectorPort()).isEqualTo(PORT);

DebuggerJmxConnectorService service = camelContext.hasService(DebuggerJmxConnectorService.class);
assertThat(service).isNotNull();
assertThat(service.isStarted()).isTrue();
}

@Test
void shouldListenOnTheConfiguredPortWhenEnabled() {
await().atMost(20, TimeUnit.SECONDS).untilAsserted(() -> {
try (Socket socket = new Socket()) {
socket.connect(new InetSocketAddress("localhost", PORT), 1000);
assertThat(socket.isConnected()).isTrue();
}
});
}

@Configuration
static class TestConfiguration {
}
}
29 changes: 26 additions & 3 deletions docs/spring-boot/modules/ROOT/pages/starters/debug.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

Spring Boot auto-configuration for the Camel Debugger.

This starter enables the Camel Debugger in your Spring Boot application, allowing you to set breakpoints and step through Camel routes during development. The debugger integrates with IDEs and tooling through JMX.
This starter enables the Camel Debugger in your Spring Boot application, allowing you to set breakpoints and step through Camel routes during development. The debugger is controlled from Java, JMX or tooling, and can additionally expose a JMX RMI connector for remote tooling, which is disabled by default.

== Maven coordinates

Expand All @@ -17,6 +17,29 @@ This starter enables the Camel Debugger in your Spring Boot application, allowin
</dependency>
----

== Usage

Adding this starter to the classpath installs and enables the Camel Debugger. The debugger can be turned off with:

[source,properties]
----
camel.debug.enabled = false
----

=== JMX connector

Tooling that attaches to the debugger from another process, such as the IntelliJ IDEA and VS Code Camel plugins, uses a JMX RMI connector. The connector is *disabled by default*, so having this starter on the classpath never opens a listening socket on its own. Enable it explicitly when remote tooling needs to attach:

[source,properties]
----
camel.debug.jmx-connector-enabled = true
camel.debug.jmx-connector-port = 1099
----

WARNING: The JMX RMI connector is created without authentication or transport security. Anyone able to reach the port can control the debugger, suspend routes and read message payloads. Only enable it on a trusted network, and make sure the port is bound to a loopback interface or protected by a firewall.

The `camel debug` command of Camel JBang does not need this connector: it drives a Spring Boot application through the local CLI connector provided by `camel-cli-connector-starter`.

== Spring Boot Auto-Configuration

The starter supports 15 options, which are listed below.
Expand All @@ -33,8 +56,8 @@ The starter supports 15 options, which are listed below.
| camel.debug.include-exception | Trace messages to include exception if the message failed | true | Boolean
| camel.debug.include-exchange-properties | Whether to include the exchange properties in the traced message | true | Boolean
| camel.debug.include-exchange-variables | Whether to include the exchange variables in the traced message | true | Boolean
| camel.debug.jmx-connector-enabled | Whether to create JMX connector that allows tooling to control the Camel debugger. This is what the IDEA and VSCode tooling is using. | true | Boolean
| camel.debug.jmx-connector-port | Port number to expose a JMX RMI connector for tooling that needs to control the debugger. | 1099 | Integer
| camel.debug.jmx-connector-enabled | Whether to create JMX connector that allows tooling to control the Camel debugger. This is what the IDEA and VSCode tooling is using. The connector opens an RMI registry and a JMX RMI server on the configured port, without authentication or transport security, so it is disabled by default and must be turned on explicitly. Only enable it on a trusted network, and bind or firewall the port accordingly. | false | Boolean
| camel.debug.jmx-connector-port | Port number to expose a JMX RMI connector for tooling that needs to control the debugger. Only in use when the JMX connector is enabled. | 1099 | Integer
| camel.debug.logging-level | The debugger logging level to use when logging activity. | info | LoggingLevel
| camel.debug.single-step-include-start-end | 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
Expand Down
Loading