This is an automated email from the ASF dual-hosted git repository.
jamesnetherton pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git
The following commit(s) were added to refs/heads/main by this push:
new 604a33e978 Add camel-console management endpoint
604a33e978 is described below
commit 604a33e978f9f4aaea75f4e5da0d6520d115ea88
Author: James Netherton <[email protected]>
AuthorDate: Thu Feb 13 11:23:34 2025 +0000
Add camel-console management endpoint
Fixes #6997
---
.../ROOT/pages/reference/extensions/console.adoc | 80 +++++++++++++++
extensions-jvm/console/deployment/pom.xml | 9 ++
.../console/deployment/ConsoleProcessor.java | 69 ++++++++++++-
.../component/console/ConsoleDisabledTest.java | 18 ++--
.../ConsoleEnabledWithCamelMainPropertyTest.java | 20 ++--
.../ConsoleManagementEndpointCustomPathTest.java | 28 +++--
.../component/console/ConsoleNotExposedTest.java | 20 ++--
extensions-jvm/console/runtime/pom.xml | 4 +
.../console/runtime/src/main/doc/usage.adoc | 40 ++++++++
.../component/console/CamelConsoleConfig.java | 53 ++++++++++
.../component/console/CamelConsoleRecorder.java | 113 +++++++++++++++++++++
.../src/main/resources/application.properties | 17 ++++
.../quarkus/component/console/it/ConsoleTest.java | 41 ++++++++
13 files changed, 475 insertions(+), 37 deletions(-)
diff --git a/docs/modules/ROOT/pages/reference/extensions/console.adoc
b/docs/modules/ROOT/pages/reference/extensions/console.adoc
index fcbb1132bd..497814c6f1 100644
--- a/docs/modules/ROOT/pages/reference/extensions/console.adoc
+++ b/docs/modules/ROOT/pages/reference/extensions/console.adoc
@@ -39,3 +39,83 @@ Please refer to the above link for usage and configuration
details.
ifeval::[{doc-show-user-guide-link} == true]
Check the xref:user-guide/index.adoc[User guide] for more information about
writing Camel Quarkus applications.
endif::[]
+
+[id="extensions-console-usage"]
+== Usage
+[id="extensions-console-usage-developer-console-endpoint"]
+=== Developer console endpoint
+
+To access the developer console, you must first enable it by adding
configuration to `application.properties`.
+
+[source,properties]
+----
+quarkus.camel.console.enabled=true
+----
+
+Alternatively you can use a `camel-main` configuration option.
+
+[source,properties]
+----
+camel.main.dev-console-enabled=true
+----
+
+The console is then available at the following URL.
+
+[source,text]
+----
+http://localhost:8080/q/camel/dev-console
+----
+
+You can then call a console by its id, such as `routes`:
+
+[source,text]
+----
+http://localhost:8080/q/camel/dev-console/routes
+----
+
+[id="extensions-console-usage-exposing-the-developer-console-in-prod-mode"]
+=== Exposing the developer console in prod mode
+
+By default, the console is only exposed in dev and test modes. To expose the
console in prod mode, add the following configuration to
`application.properties`.
+
+[source,properties]
+----
+quarkus.camel.console.exposure-mode=ALL
+----
+
+See the configuration overview below for further details about `exposure-mode`.
+
+
+[id="extensions-console-additional-camel-quarkus-configuration"]
+== Additional Camel Quarkus configuration
+
+[width="100%",cols="80,5,15",options="header"]
+|===
+| Configuration property | Type | Default
+
+
+|icon:lock[title=Fixed at build time]
[[quarkus.camel.console.enabled]]`link:#quarkus.camel.console.enabled[quarkus.camel.console.enabled]`
+
+Whether the Camel developer console is enabled.
+| `boolean`
+| `false`
+
+|icon:lock[title=Fixed at build time]
[[quarkus.camel.console.path]]`link:#quarkus.camel.console.path[quarkus.camel.console.path]`
+
+The context path under which the Camel developer console is deployed (default
/q/camel/dev-console).
+| `string`
+| `camel/dev-console`
+
+|icon:lock[title=Fixed at build time]
[[quarkus.camel.console.exposure-mode]]`link:#quarkus.camel.console.exposure-mode[quarkus.camel.console.exposure-mode]`
+
+The modes in which the Camel developer console is available. The default
{@code dev-test} enables the developer
+console only in dev mode and test modes.
+A value of {@code all} enables agent discovery in dev, test and prod modes.
Setting the value to {@code none} will
+not expose the developer console HTTP endpoint.
+| `all`, `dev-test`, `none`
+| `dev-test`
+|===
+
+[.configuration-legend]
+{doc-link-icon-lock}[title=Fixed at build time] Configuration property fixed
at build time. All other configuration properties are overridable at runtime.
+
diff --git a/extensions-jvm/console/deployment/pom.xml
b/extensions-jvm/console/deployment/pom.xml
index 4563fd6da4..5dd3e3613b 100644
--- a/extensions-jvm/console/deployment/pom.xml
+++ b/extensions-jvm/console/deployment/pom.xml
@@ -30,6 +30,10 @@
<name>Camel Quarkus :: Console :: Deployment</name>
<dependencies>
+ <dependency>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-vertx-http-deployment</artifactId>
+ </dependency>
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-core-deployment</artifactId>
@@ -44,6 +48,11 @@
<artifactId>quarkus-junit5-internal</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>io.rest-assured</groupId>
+ <artifactId>rest-assured</artifactId>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-stub</artifactId>
diff --git
a/extensions-jvm/console/deployment/src/main/java/org/apache/camel/quarkus/component/console/deployment/ConsoleProcessor.java
b/extensions-jvm/console/deployment/src/main/java/org/apache/camel/quarkus/component/console/deployment/ConsoleProcessor.java
index 789f2187d5..60a66ccbd7 100644
---
a/extensions-jvm/console/deployment/src/main/java/org/apache/camel/quarkus/component/console/deployment/ConsoleProcessor.java
+++
b/extensions-jvm/console/deployment/src/main/java/org/apache/camel/quarkus/component/console/deployment/ConsoleProcessor.java
@@ -16,18 +16,33 @@
*/
package org.apache.camel.quarkus.component.console.deployment;
+import java.util.function.BooleanSupplier;
+import java.util.function.Consumer;
+
+import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
+import io.quarkus.deployment.annotations.BuildSteps;
import io.quarkus.deployment.annotations.ExecutionTime;
import io.quarkus.deployment.annotations.Record;
import io.quarkus.deployment.builditem.FeatureBuildItem;
import io.quarkus.deployment.pkg.steps.NativeOrNativeSourcesBuild;
+import io.quarkus.runtime.LaunchMode;
+import io.quarkus.vertx.http.deployment.NonApplicationRootPathBuildItem;
+import io.quarkus.vertx.http.deployment.RouteBuildItem;
+import io.vertx.core.Handler;
+import io.vertx.ext.web.Route;
+import io.vertx.ext.web.RoutingContext;
+import org.apache.camel.quarkus.component.console.CamelConsoleConfig;
+import org.apache.camel.quarkus.component.console.CamelConsoleRecorder;
import org.apache.camel.quarkus.core.JvmOnlyRecorder;
+import org.apache.camel.quarkus.core.deployment.spi.CamelContextBuildItem;
import org.apache.camel.quarkus.core.deployment.spi.CamelServiceDestination;
import
org.apache.camel.quarkus.core.deployment.spi.CamelServicePatternBuildItem;
+import org.eclipse.microprofile.config.ConfigProvider;
import org.jboss.logging.Logger;
+@BuildSteps(onlyIf = ConsoleProcessor.CamelConsoleEnabled.class)
class ConsoleProcessor {
-
private static final Logger LOG = Logger.getLogger(ConsoleProcessor.class);
private static final String FEATURE = "camel-console";
@@ -42,6 +57,41 @@ class ConsoleProcessor {
"META-INF/services/org/apache/camel/dev-console/*");
}
+ @BuildStep
+ @Record(ExecutionTime.STATIC_INIT)
+ void initDevConsoleRegistry(
+ CamelContextBuildItem camelContext,
+ CamelConsoleRecorder recorder) {
+ recorder.initDevConsoleRegistry(camelContext.getCamelContext());
+ }
+
+ @BuildStep
+ @Record(ExecutionTime.RUNTIME_INIT)
+ void createManagementRoute(
+ CamelContextBuildItem camelContext,
+ NonApplicationRootPathBuildItem nonApplicationRootPathBuildItem,
+ BuildProducer<RouteBuildItem> routes,
+ CamelConsoleConfig config,
+ CamelConsoleRecorder recorder) {
+
+ if (canExposeManagementEndpoint(config)) {
+ Consumer<Route> route = recorder.route();
+ Handler<RoutingContext> handler =
recorder.getHandler(camelContext.getCamelContext());
+
+ routes.produce(nonApplicationRootPathBuildItem.routeBuilder()
+ .management()
+ .routeFunction(config.path(), route)
+ .handler(handler)
+ .build());
+
+ routes.produce(nonApplicationRootPathBuildItem.routeBuilder()
+ .management()
+ .routeFunction(config.path() + "/:id", route)
+ .handler(handler)
+ .build());
+ }
+ }
+
/**
* Remove this once this extension starts supporting the native mode.
*/
@@ -51,4 +101,21 @@ class ConsoleProcessor {
JvmOnlyRecorder.warnJvmInNative(LOG, FEATURE); // warn at build time
recorder.warnJvmInNative(FEATURE); // warn at runtime
}
+
+ private static boolean canExposeManagementEndpoint(CamelConsoleConfig
config) {
+ return (LaunchMode.current().isDevOrTest()
+ && config.exposureMode() ==
CamelConsoleConfig.ExposureMode.DEV_TEST)
+ ||
config.exposureMode().equals(CamelConsoleConfig.ExposureMode.ALL);
+ }
+
+ static final class CamelConsoleEnabled implements BooleanSupplier {
+ CamelConsoleConfig config;
+
+ @Override
+ public boolean getAsBoolean() {
+ return config.enabled() || ConfigProvider.getConfig()
+ .getOptionalValue("camel.main.dev-console-enabled",
Boolean.class)
+ .orElse(false);
+ }
+ }
}
diff --git
a/integration-tests-jvm/console/src/test/java/org/apache/camel/quarkus/component/console/it/ConsoleTest.java
b/extensions-jvm/console/deployment/src/test/java/org/apache/camel/quarkus/component/console/ConsoleDisabledTest.java
similarity index 69%
copy from
integration-tests-jvm/console/src/test/java/org/apache/camel/quarkus/component/console/it/ConsoleTest.java
copy to
extensions-jvm/console/deployment/src/test/java/org/apache/camel/quarkus/component/console/ConsoleDisabledTest.java
index f06127b8a6..ebc62d6f1d 100644
---
a/integration-tests-jvm/console/src/test/java/org/apache/camel/quarkus/component/console/it/ConsoleTest.java
+++
b/extensions-jvm/console/deployment/src/test/java/org/apache/camel/quarkus/component/console/ConsoleDisabledTest.java
@@ -14,21 +14,21 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.camel.quarkus.component.console.it;
+package org.apache.camel.quarkus.component.console;
-import io.quarkus.test.junit.QuarkusTest;
+import io.quarkus.test.QuarkusUnitTest;
import io.restassured.RestAssured;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
-import static org.hamcrest.Matchers.is;
+class ConsoleDisabledTest {
+ @RegisterExtension
+ static final QuarkusUnitTest CONFIG = new
QuarkusUnitTest().withEmptyApplication();
-@QuarkusTest
-class ConsoleTest {
@Test
- public void resolveContextDevConsole() {
- RestAssured.get("/console/context")
+ void managementEndpointDisabled() {
+ RestAssured.get("/q/camel/dev-console")
.then()
- .statusCode(200)
- .body(is("context"));
+ .statusCode(404);
}
}
diff --git
a/integration-tests-jvm/console/src/test/java/org/apache/camel/quarkus/component/console/it/ConsoleTest.java
b/extensions-jvm/console/deployment/src/test/java/org/apache/camel/quarkus/component/console/ConsoleEnabledWithCamelMainPropertyTest.java
similarity index 64%
copy from
integration-tests-jvm/console/src/test/java/org/apache/camel/quarkus/component/console/it/ConsoleTest.java
copy to
extensions-jvm/console/deployment/src/test/java/org/apache/camel/quarkus/component/console/ConsoleEnabledWithCamelMainPropertyTest.java
index f06127b8a6..c4c441bd77 100644
---
a/integration-tests-jvm/console/src/test/java/org/apache/camel/quarkus/component/console/it/ConsoleTest.java
+++
b/extensions-jvm/console/deployment/src/test/java/org/apache/camel/quarkus/component/console/ConsoleEnabledWithCamelMainPropertyTest.java
@@ -14,21 +14,23 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.camel.quarkus.component.console.it;
+package org.apache.camel.quarkus.component.console;
-import io.quarkus.test.junit.QuarkusTest;
+import io.quarkus.test.QuarkusUnitTest;
import io.restassured.RestAssured;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
-import static org.hamcrest.Matchers.is;
+class ConsoleEnabledWithCamelMainPropertyTest {
+ @RegisterExtension
+ static final QuarkusUnitTest CONFIG = new QuarkusUnitTest()
+ .withEmptyApplication()
+ .overrideConfigKey("camel.main.dev-console-enabled", "true");
-@QuarkusTest
-class ConsoleTest {
@Test
- public void resolveContextDevConsole() {
- RestAssured.get("/console/context")
+ void managementEndpointEnabled() {
+ RestAssured.get("/q/camel/dev-console")
.then()
- .statusCode(200)
- .body(is("context"));
+ .statusCode(200);
}
}
diff --git
a/integration-tests-jvm/console/src/test/java/org/apache/camel/quarkus/component/console/it/ConsoleTest.java
b/extensions-jvm/console/deployment/src/test/java/org/apache/camel/quarkus/component/console/ConsoleManagementEndpointCustomPathTest.java
similarity index 54%
copy from
integration-tests-jvm/console/src/test/java/org/apache/camel/quarkus/component/console/it/ConsoleTest.java
copy to
extensions-jvm/console/deployment/src/test/java/org/apache/camel/quarkus/component/console/ConsoleManagementEndpointCustomPathTest.java
index f06127b8a6..df98b99a08 100644
---
a/integration-tests-jvm/console/src/test/java/org/apache/camel/quarkus/component/console/it/ConsoleTest.java
+++
b/extensions-jvm/console/deployment/src/test/java/org/apache/camel/quarkus/component/console/ConsoleManagementEndpointCustomPathTest.java
@@ -14,21 +14,31 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.camel.quarkus.component.console.it;
+package org.apache.camel.quarkus.component.console;
-import io.quarkus.test.junit.QuarkusTest;
+import io.quarkus.test.QuarkusUnitTest;
import io.restassured.RestAssured;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
-import static org.hamcrest.Matchers.is;
+class ConsoleManagementEndpointCustomPathTest {
+ @RegisterExtension
+ static final QuarkusUnitTest CONFIG = new QuarkusUnitTest()
+ .withEmptyApplication()
+ .overrideConfigKey("quarkus.camel.console.enabled", "true")
+ .overrideConfigKey("quarkus.camel.console.path", "camel/other");
-@QuarkusTest
-class ConsoleTest {
@Test
- public void resolveContextDevConsole() {
- RestAssured.get("/console/context")
+ void alternateManagementEndpointPath() {
+ RestAssured.get("/q/camel/other")
.then()
- .statusCode(200)
- .body(is("context"));
+ .statusCode(200);
+ }
+
+ @Test
+ void alternateManagementEndpointPathWithId() {
+ RestAssured.get("/q/camel/other/context")
+ .then()
+ .statusCode(200);
}
}
diff --git
a/integration-tests-jvm/console/src/test/java/org/apache/camel/quarkus/component/console/it/ConsoleTest.java
b/extensions-jvm/console/deployment/src/test/java/org/apache/camel/quarkus/component/console/ConsoleNotExposedTest.java
similarity index 64%
copy from
integration-tests-jvm/console/src/test/java/org/apache/camel/quarkus/component/console/it/ConsoleTest.java
copy to
extensions-jvm/console/deployment/src/test/java/org/apache/camel/quarkus/component/console/ConsoleNotExposedTest.java
index f06127b8a6..93c0c11366 100644
---
a/integration-tests-jvm/console/src/test/java/org/apache/camel/quarkus/component/console/it/ConsoleTest.java
+++
b/extensions-jvm/console/deployment/src/test/java/org/apache/camel/quarkus/component/console/ConsoleNotExposedTest.java
@@ -14,21 +14,23 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.camel.quarkus.component.console.it;
+package org.apache.camel.quarkus.component.console;
-import io.quarkus.test.junit.QuarkusTest;
+import io.quarkus.test.QuarkusUnitTest;
import io.restassured.RestAssured;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
-import static org.hamcrest.Matchers.is;
+class ConsoleNotExposedTest {
+ @RegisterExtension
+ static final QuarkusUnitTest CONFIG = new QuarkusUnitTest()
+ .withEmptyApplication()
+ .overrideConfigKey("quarkus.camel.console.exposure-mode", "none");
-@QuarkusTest
-class ConsoleTest {
@Test
- public void resolveContextDevConsole() {
- RestAssured.get("/console/context")
+ void managementEndpointNotExposed() {
+ RestAssured.get("/q/camel/dev-console")
.then()
- .statusCode(200)
- .body(is("context"));
+ .statusCode(404);
}
}
diff --git a/extensions-jvm/console/runtime/pom.xml
b/extensions-jvm/console/runtime/pom.xml
index 960901bf3f..59c6b0e700 100644
--- a/extensions-jvm/console/runtime/pom.xml
+++ b/extensions-jvm/console/runtime/pom.xml
@@ -35,6 +35,10 @@
</properties>
<dependencies>
+ <dependency>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-vertx-http</artifactId>
+ </dependency>
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-core</artifactId>
diff --git a/extensions-jvm/console/runtime/src/main/doc/usage.adoc
b/extensions-jvm/console/runtime/src/main/doc/usage.adoc
new file mode 100644
index 0000000000..4f4c6f6dd8
--- /dev/null
+++ b/extensions-jvm/console/runtime/src/main/doc/usage.adoc
@@ -0,0 +1,40 @@
+=== Developer console endpoint
+
+To access the developer console, you must first enable it by adding
configuration to `application.properties`.
+
+[source,properties]
+----
+quarkus.camel.console.enabled=true
+----
+
+Alternatively you can use a `camel-main` configuration option.
+
+[source,properties]
+----
+camel.main.dev-console-enabled=true
+----
+
+The console is then available at the following URL.
+
+[source,text]
+----
+http://localhost:8080/q/camel/dev-console
+----
+
+You can then call a console by its id, such as `routes`:
+
+[source,text]
+----
+http://localhost:8080/q/camel/dev-console/routes
+----
+
+=== Exposing the developer console in prod mode
+
+By default, the console is only exposed in dev and test modes. To expose the
console in prod mode, add the following configuration to
`application.properties`.
+
+[source,properties]
+----
+quarkus.camel.console.exposure-mode=ALL
+----
+
+See the configuration overview below for further details about `exposure-mode`.
diff --git
a/extensions-jvm/console/runtime/src/main/java/org/apache/camel/quarkus/component/console/CamelConsoleConfig.java
b/extensions-jvm/console/runtime/src/main/java/org/apache/camel/quarkus/component/console/CamelConsoleConfig.java
new file mode 100644
index 0000000000..89e3234805
--- /dev/null
+++
b/extensions-jvm/console/runtime/src/main/java/org/apache/camel/quarkus/component/console/CamelConsoleConfig.java
@@ -0,0 +1,53 @@
+/*
+ * 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.quarkus.component.console;
+
+import io.quarkus.runtime.annotations.ConfigPhase;
+import io.quarkus.runtime.annotations.ConfigRoot;
+import io.smallrye.config.ConfigMapping;
+import io.smallrye.config.WithDefault;
+
+@ConfigRoot(phase = ConfigPhase.BUILD_AND_RUN_TIME_FIXED)
+@ConfigMapping(prefix = "quarkus.camel.console")
+public interface CamelConsoleConfig {
+ /**
+ * Whether the Camel developer console is enabled.
+ */
+ @WithDefault("false")
+ boolean enabled();
+
+ /**
+ * The context path under which the Camel developer console is deployed
(default /q/camel/dev-console).
+ */
+ @WithDefault("camel/dev-console")
+ String path();
+
+ /**
+ * The modes in which the Camel developer console is available. The
default {@code dev-test} enables the developer
+ * console only in dev mode and test modes.
+ * A value of {@code all} enables agent discovery in dev, test and prod
modes. Setting the value to {@code none} will
+ * not expose the developer console HTTP endpoint.
+ */
+ @WithDefault("DEV_TEST")
+ ExposureMode exposureMode();
+
+ enum ExposureMode {
+ ALL,
+ DEV_TEST,
+ NONE,
+ }
+}
diff --git
a/extensions-jvm/console/runtime/src/main/java/org/apache/camel/quarkus/component/console/CamelConsoleRecorder.java
b/extensions-jvm/console/runtime/src/main/java/org/apache/camel/quarkus/component/console/CamelConsoleRecorder.java
new file mode 100644
index 0000000000..f88ff78be7
--- /dev/null
+++
b/extensions-jvm/console/runtime/src/main/java/org/apache/camel/quarkus/component/console/CamelConsoleRecorder.java
@@ -0,0 +1,113 @@
+/*
+ * 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.quarkus.component.console;
+
+import java.util.Map;
+import java.util.function.Consumer;
+
+import io.quarkus.runtime.RuntimeValue;
+import io.quarkus.runtime.annotations.Recorder;
+import io.vertx.core.Handler;
+import io.vertx.core.http.HttpServerResponse;
+import io.vertx.core.json.JsonObject;
+import io.vertx.ext.web.Route;
+import io.vertx.ext.web.RoutingContext;
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.console.DevConsole;
+import org.apache.camel.console.DevConsoleRegistry;
+import org.apache.camel.util.ObjectHelper;
+
+@Recorder
+public class CamelConsoleRecorder {
+ public Consumer<Route> route() {
+ return new Consumer<Route>() {
+ @Override
+ public void accept(Route route) {
+ route.produces("application/json");
+ }
+ };
+ }
+
+ public Handler<RoutingContext> getHandler(RuntimeValue<CamelContext>
contextRuntimeValue) {
+ CamelContext context = contextRuntimeValue.getValue();
+ DevConsoleRegistry devConsoleRegistry =
context.getCamelContextExtension().getContextPlugin(DevConsoleRegistry.class);
+ return new CamelConsoleHandler(devConsoleRegistry);
+ }
+
+ public void initDevConsoleRegistry(RuntimeValue<CamelContext>
camelContextRuntimeValue) {
+ camelContextRuntimeValue.getValue()
+ .getCamelContextExtension()
+ .getContextPlugin(DevConsoleRegistry.class)
+ .loadDevConsoles();
+ }
+
+ static final class CamelConsoleHandler implements Handler<RoutingContext> {
+ private final DevConsoleRegistry devConsoleRegistry;
+
+ CamelConsoleHandler(DevConsoleRegistry devConsoleRegistry) {
+ this.devConsoleRegistry = devConsoleRegistry;
+ }
+
+ @Override
+ public void handle(RoutingContext context) {
+ if (devConsoleRegistry != null && devConsoleRegistry.isEnabled()) {
+ String id = context.pathParam("id");
+ if (ObjectHelper.isNotEmpty(id)) {
+ getConsoleById(context, id);
+ } else {
+ getConsoles(context);
+ }
+ }
+ }
+
+ void getConsoles(RoutingContext context) {
+ JsonObject root = new JsonObject();
+ devConsoleRegistry.stream().forEach(devConsole -> {
+ JsonObject console = new JsonObject();
+ console.put("id", devConsole.getId());
+ console.put("displayName", devConsole.getDisplayName());
+ console.put("description", devConsole.getDescription());
+ root.put(devConsole.getId(), console);
+ });
+ writeResponse(context.response(), root);
+ }
+
+ void getConsoleById(RoutingContext context, String id) {
+ JsonObject root = new JsonObject();
+ devConsoleRegistry.stream().sorted((o1, o2) -> {
+ int p1 = id.indexOf(o1.getId());
+ int p2 = id.indexOf(o2.getId());
+ return Integer.compare(p1, p2);
+ }).forEach(devConsole -> {
+ boolean include = "all".equals(id) ||
id.contains(devConsole.getId());
+ if (include &&
devConsole.supportMediaType(DevConsole.MediaType.JSON)) {
+ Object result = devConsole.call(DevConsole.MediaType.JSON,
Map.of(Exchange.HTTP_PATH, id));
+ if (result != null) {
+ root.put(devConsole.getId(), result);
+ }
+ }
+ });
+ writeResponse(context.response(), root);
+ }
+
+ void writeResponse(HttpServerResponse response, JsonObject jsonObject)
{
+ response.putHeader("Content-Type", "application/json");
+ response.end(jsonObject.encode());
+ }
+ }
+}
diff --git
a/integration-tests-jvm/console/src/main/resources/application.properties
b/integration-tests-jvm/console/src/main/resources/application.properties
new file mode 100644
index 0000000000..c467323045
--- /dev/null
+++ b/integration-tests-jvm/console/src/main/resources/application.properties
@@ -0,0 +1,17 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+quarkus.camel.console.enabled=true
\ No newline at end of file
diff --git
a/integration-tests-jvm/console/src/test/java/org/apache/camel/quarkus/component/console/it/ConsoleTest.java
b/integration-tests-jvm/console/src/test/java/org/apache/camel/quarkus/component/console/it/ConsoleTest.java
index f06127b8a6..e277a3d40d 100644
---
a/integration-tests-jvm/console/src/test/java/org/apache/camel/quarkus/component/console/it/ConsoleTest.java
+++
b/integration-tests-jvm/console/src/test/java/org/apache/camel/quarkus/component/console/it/ConsoleTest.java
@@ -16,11 +16,18 @@
*/
package org.apache.camel.quarkus.component.console.it;
+import java.util.Map;
+
import io.quarkus.test.junit.QuarkusTest;
import io.restassured.RestAssured;
+import io.restassured.path.json.JsonPath;
+import org.apache.camel.ServiceStatus;
import org.junit.jupiter.api.Test;
+import static org.hamcrest.Matchers.anEmptyMap;
import static org.hamcrest.Matchers.is;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
@QuarkusTest
class ConsoleTest {
@@ -31,4 +38,38 @@ class ConsoleTest {
.statusCode(200)
.body(is("context"));
}
+
+ @Test
+ void listConsoles() {
+ JsonPath response = RestAssured.get("/q/camel/dev-console")
+ .then()
+ .statusCode(200)
+ .extract()
+ .response()
+ .jsonPath();
+
+ Map<Object, Object> consoles = response.getMap("$");
+ assertFalse(consoles.isEmpty());
+ assertTrue(consoles.containsKey("bean"));
+ assertTrue(consoles.containsKey("blocked"));
+ assertTrue(consoles.containsKey("browse"));
+ assertTrue(consoles.containsKey("context"));
+ }
+
+ @Test
+ void invokeConsole() {
+ RestAssured.get("/q/camel/dev-console/context")
+ .then()
+ .statusCode(200)
+ .body("context.name", is("camel-1"),
+ "context.state", is(ServiceStatus.Started.name()));
+ }
+
+ @Test
+ void invokeInvalidConsole() {
+ RestAssured.get("/q/camel/dev-console/foo")
+ .then()
+ .statusCode(200)
+ .body("", anEmptyMap());
+ }
}