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 02868c249210 CAMEL-24661: camel-jbang - --console with the Spring Boot
and Quarkus runtimes
02868c249210 is described below
commit 02868c249210a6d0971ea86c59dbbef3af2a5522
Author: Claus Ibsen <[email protected]>
AuthorDate: Thu Sep 17 12:21:32 2026 +0200
CAMEL-24661: camel-jbang - --console with the Spring Boot and Quarkus
runtimes
camel run --console and camel export --console only enabled the developer
console with Camel Main. All three runtimes now support it, each on its own
path: /q/dev (jbang, Camel Main), /actuator/camel or /observe/camel with
--observe (Spring Boot), /q/camel/dev-console (Quarkus). The console is
enabled with the shared camel.main.devConsoleEnabled option, and Run passes
--observe and --console on to the Spring Boot and Quarkus exporters as well.
Because the console has no authentication, camel export --console adds the
dependency to the pom but enables the console only in the dev profile
(application-dev.properties, appended if present), so it is absent from a
prod build. camel run enables it in its temporary project regardless of the
profile, passing quarkus.camel.console.exposure-mode=ALL to the Maven build
for Quarkus without touching any project file. On Spring Boot the camel
actuator endpoint is merged into management.endpoints.web.exposure.include
without duplicating ids.
Documented in the camel-jbang managing and running pages, with ExportTest
coverage across the three runtimes.
Closes #26542
Co-authored-by: Claude <[email protected]>
---
.../modules/ROOT/pages/camel-jbang-managing.adoc | 17 +++
.../modules/ROOT/pages/camel-jbang-running.adoc | 8 +-
.../pages/jbang-commands/camel-jbang-debug.adoc | 2 +-
.../camel-jbang-dependency-copy.adoc | 2 +-
.../camel-jbang-dependency-list.adoc | 2 +-
.../camel-jbang-dependency-update.adoc | 2 +-
.../ROOT/pages/jbang-commands/camel-jbang-dev.adoc | 2 +-
.../pages/jbang-commands/camel-jbang-export.adoc | 2 +-
.../ROOT/pages/jbang-commands/camel-jbang-run.adoc | 2 +-
.../pages/jbang-commands/camel-jbang-sbom.adoc | 2 +-
.../META-INF/camel-jbang-commands-metadata.json | 12 +-
.../dsl/jbang/core/commands/ExportBaseCommand.java | 75 +++++++++-
.../dsl/jbang/core/commands/ExportCamelMain.java | 17 ++-
.../dsl/jbang/core/commands/ExportQuarkus.java | 15 ++
.../dsl/jbang/core/commands/ExportSpringBoot.java | 59 +++++++-
.../apache/camel/dsl/jbang/core/commands/Run.java | 17 ++-
.../camel/dsl/jbang/core/commands/ExportTest.java | 161 ++++++++++++++++++---
.../devprofile/application-dev.properties | 17 +++
.../src/test/resources/devprofile/hello.yaml | 28 ++++
19 files changed, 387 insertions(+), 55 deletions(-)
diff --git a/docs/user-manual/modules/ROOT/pages/camel-jbang-managing.adoc
b/docs/user-manual/modules/ROOT/pages/camel-jbang-managing.adoc
index 6e55603866cf..b7ebddc1a4d7 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-jbang-managing.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-jbang-managing.adoc
@@ -288,6 +288,23 @@ camel run hello.java --console
The console is accessible at http://localhost:8080/q/dev and provides insights
into routes,
performance, and EIP-level metrics. The endpoints support both HTTP GET and
POST.
+When running with xref:camel-jbang-running.adoc#_runtimes[another runtime],
the console is served where
+that runtime puts it:
+
+[width="100%",cols="2,4,4",options="header"]
+|===
+| Runtime | `--console` | `--console --observe`
+| jbang, Camel Main | `http://localhost:8080/q/dev` |
`http://localhost:9876/q/dev` (on the management port)
+| Spring Boot | `http://localhost:8080/actuator/camel` (the `camel` actuator
endpoint) | `http://localhost:9876/observe/camel`
+| Quarkus | `http://localhost:8080/q/camel/dev-console` |
`http://localhost:8080/q/camel/dev-console`
+|===
+
+The console has no authentication, so it is meant for development only. `camel
export --console` therefore
+includes the console dependency in the exported project, but only enables it
in `application-dev.properties`,
+so the console is there when the project runs with the dev profile
(`camel.main.profile=dev` with Camel Main,
+`spring.profiles.active=dev` with Spring Boot, and `quarkus:dev` with Quarkus)
and not in a production build.
+With `camel export --profile=dev` the dev profile is flattened into
`application.properties`, and so is the console.
+
GET with query parameters:
[source,bash]
diff --git a/docs/user-manual/modules/ROOT/pages/camel-jbang-running.adoc
b/docs/user-manual/modules/ROOT/pages/camel-jbang-running.adoc
index ea0b9443b16b..a835b0948e79 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-jbang-running.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-jbang-running.adoc
@@ -259,7 +259,9 @@ This is the same JVM you would get from `camel export`, and
is what the Camel TU
launching examples and folders.
The options `--profile`, `--port`, `--prop`, `--max-seconds`,
`--max-messages`, `--max-idle-seconds`,
-`--jvm-args` and `--jfr` are passed to the application on all three runtimes.
The application logs to a
+`--jvm-args`, `--jfr`, `--observe` and `--console` are passed to the
application on all three runtimes
+(each runtime serves the developer console on its own path, see
+xref:camel-jbang-managing.adoc#_developer_console[Developer Console]). The
application logs to a
file in `~/.camel` so `camel log` and the TUI can read the logs: `<pid>.log`
for Spring Boot, and
`<name>.log` for Quarkus and Camel Main (`<name>` is the name the application
reports, from `--name` or
else the first route file).
@@ -269,9 +271,7 @@ Limitations compared to the `jbang` runtime:
- Startup is slower, as the project must be built with Maven first (the first
run also downloads
the Maven wrapper and plugins).
- New components cannot be auto-detected while running (stop and run again to
update dependencies).
-- `--console` is supported with Camel Main (the exported project enables the
developer console, health, info
- and Jolokia), but not yet with Spring Boot and Quarkus. The deprecated
`--health` and `--metrics` options
- are not supported in a separate JVM; use `--observe` instead.
+- The deprecated `--health` and `--metrics` options are not supported in a
separate JVM; use `--observe` instead.
- Options that only work in-process are not supported: `--background`,
`--code`, `--open-api`,
`--empty` and `--mcp-stdio`.
- Dev mode reloads YAML and XML route files from the original source
directory; Java sources cannot
diff --git
a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-debug.adoc
b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-debug.adoc
index 113de9e29b8e..8b197c2c638a 100644
--- a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-debug.adoc
+++ b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-debug.adoc
@@ -27,7 +27,7 @@ camel debug [options]
| `--camel-spring-boot-version` | To run using a different Camel Spring Boot
version than the default version. | | String
| `--camel-version` | To run using a different Camel version than the default
version. | | String
| `--code` | Run the given text or file as Java DSL routes | | String
-| `--console` | Developer console at /q/dev on local HTTP server (port 8080 by
default) | false | boolean
+| `--console` | Developer console on the local HTTP server (port 8080 by
default): /q/dev with the jbang and Camel Main runtimes, /actuator/camel with
Spring Boot, and /q/camel/dev-console with Quarkus | false | boolean
| `--dep,--dependency` | Add additional dependencies | | List
| `--download` | Whether to allow automatic downloading JAR dependencies (over
the internet) | true | boolean
| `--empty` | Run an empty Camel without loading source files | false | boolean
diff --git
a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-dependency-copy.adoc
b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-dependency-copy.adoc
index 45262e173d18..5e3e2bf5bffc 100644
---
a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-dependency-copy.adoc
+++
b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-dependency-copy.adoc
@@ -24,7 +24,7 @@ camel dependency copy [options]
| `--camel-version` | To export using a different Camel version than the
default version. | | String
| `--camel-wrapper` | Include Camel Wrapper scripts in exported project for
version pinning | false | boolean
| `--clean-dir` | If exporting to current directory (default) then all
existing files are preserved. Enabling this option will force cleaning current
directory including all sub dirs (use this with care) | false | boolean
-| `--console` | Developer console at /q/dev on local HTTP server (port 8080 by
default). Camel Main runtime only. | false | boolean
+| `--console` | Developer console on the local HTTP server (port 8080 by
default): /q/dev with Camel Main, /actuator/camel with Spring Boot, and
/q/camel/dev-console with Quarkus. The exported project only has the console
with the dev profile. | false | boolean
| `--dep,--dependency` | Add additional dependencies | | List
| `--dir,--directory` | Directory where the project will be exported | . |
String
| `--docker` | Include Docker files in exported project | true | boolean
diff --git
a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-dependency-list.adoc
b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-dependency-list.adoc
index 2acf69d415cb..b19112ed423d 100644
---
a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-dependency-list.adoc
+++
b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-dependency-list.adoc
@@ -24,7 +24,7 @@ camel dependency list [options]
| `--camel-version` | To export using a different Camel version than the
default version. | | String
| `--camel-wrapper` | Include Camel Wrapper scripts in exported project for
version pinning | false | boolean
| `--clean-dir` | If exporting to current directory (default) then all
existing files are preserved. Enabling this option will force cleaning current
directory including all sub dirs (use this with care) | false | boolean
-| `--console` | Developer console at /q/dev on local HTTP server (port 8080 by
default). Camel Main runtime only. | false | boolean
+| `--console` | Developer console on the local HTTP server (port 8080 by
default): /q/dev with Camel Main, /actuator/camel with Spring Boot, and
/q/camel/dev-console with Quarkus. The exported project only has the console
with the dev profile. | false | boolean
| `--dep,--dependency` | Add additional dependencies | | List
| `--dir,--directory` | Directory where the project will be exported | . |
String
| `--docker` | Include Docker files in exported project | true | boolean
diff --git
a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-dependency-update.adoc
b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-dependency-update.adoc
index 4e2e7f9ef4e8..f57b34e05856 100644
---
a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-dependency-update.adoc
+++
b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-dependency-update.adoc
@@ -25,7 +25,7 @@ camel dependency update [options]
| `--camel-wrapper` | Include Camel Wrapper scripts in exported project for
version pinning | false | boolean
| `--clean` | Regenerate list of dependencies (do not keep existing
dependencies). Not supported for pom.xml | | boolean
| `--clean-dir` | If exporting to current directory (default) then all
existing files are preserved. Enabling this option will force cleaning current
directory including all sub dirs (use this with care) | false | boolean
-| `--console` | Developer console at /q/dev on local HTTP server (port 8080 by
default). Camel Main runtime only. | false | boolean
+| `--console` | Developer console on the local HTTP server (port 8080 by
default): /q/dev with Camel Main, /actuator/camel with Spring Boot, and
/q/camel/dev-console with Quarkus. The exported project only has the console
with the dev profile. | false | boolean
| `--dep,--dependency` | Add additional dependencies | | List
| `--dir,--directory` | Directory where the project will be exported | . |
String
| `--docker` | Include Docker files in exported project | true | boolean
diff --git
a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-dev.adoc
b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-dev.adoc
index ad6e0e9c9f05..1a0754b29298 100644
--- a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-dev.adoc
+++ b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-dev.adoc
@@ -25,7 +25,7 @@ camel dev [options]
| `--camel-spring-boot-version` | To run using a different Camel Spring Boot
version than the default version. | | String
| `--camel-version` | To run using a different Camel version than the default
version. | | String
| `--code` | Run the given text or file as Java DSL routes | | String
-| `--console` | Developer console at /q/dev on local HTTP server (port 8080 by
default) | false | boolean
+| `--console` | Developer console on the local HTTP server (port 8080 by
default): /q/dev with the jbang and Camel Main runtimes, /actuator/camel with
Spring Boot, and /q/camel/dev-console with Quarkus | false | boolean
| `--dep,--dependency` | Add additional dependencies | | List
| `--download` | Whether to allow automatic downloading JAR dependencies (over
the internet) | true | boolean
| `--empty` | Run an empty Camel without loading source files | false | boolean
diff --git
a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-export.adoc
b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-export.adoc
index 4d15ca127f87..f0c65185b4cc 100644
--- a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-export.adoc
+++ b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-export.adoc
@@ -24,7 +24,7 @@ camel export [options]
| `--camel-version` | To export using a different Camel version than the
default version. | | String
| `--camel-wrapper` | Include Camel Wrapper scripts in exported project for
version pinning | false | boolean
| `--clean-dir` | If exporting to current directory (default) then all
existing files are preserved. Enabling this option will force cleaning current
directory including all sub dirs (use this with care) | false | boolean
-| `--console` | Developer console at /q/dev on local HTTP server (port 8080 by
default). Camel Main runtime only. | false | boolean
+| `--console` | Developer console on the local HTTP server (port 8080 by
default): /q/dev with Camel Main, /actuator/camel with Spring Boot, and
/q/camel/dev-console with Quarkus. The exported project only has the console
with the dev profile. | false | boolean
| `--dep,--dependency` | Add additional dependencies | | List
| `--dir,--directory` | Directory where the project will be exported | . |
String
| `--docker` | Include Docker files in exported project | true | boolean
diff --git
a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-run.adoc
b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-run.adoc
index af231c6a740e..067e0734f8d4 100644
--- a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-run.adoc
+++ b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-run.adoc
@@ -25,7 +25,7 @@ camel run [options]
| `--camel-spring-boot-version` | To run using a different Camel Spring Boot
version than the default version. | | String
| `--camel-version` | To run using a different Camel version than the default
version. | | String
| `--code` | Run the given text or file as Java DSL routes | | String
-| `--console` | Developer console at /q/dev on local HTTP server (port 8080 by
default) | false | boolean
+| `--console` | Developer console on the local HTTP server (port 8080 by
default): /q/dev with the jbang and Camel Main runtimes, /actuator/camel with
Spring Boot, and /q/camel/dev-console with Quarkus | false | boolean
| `--dep,--dependency` | Add additional dependencies | | List
| `--download` | Whether to allow automatic downloading JAR dependencies (over
the internet) | true | boolean
| `--empty` | Run an empty Camel without loading source files | false | boolean
diff --git
a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-sbom.adoc
b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-sbom.adoc
index 92f5448a7fb3..1842334e35fe 100644
--- a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-sbom.adoc
+++ b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-sbom.adoc
@@ -24,7 +24,7 @@ camel sbom [options]
| `--camel-version` | To export using a different Camel version than the
default version. | | String
| `--camel-wrapper` | Include Camel Wrapper scripts in exported project for
version pinning | false | boolean
| `--clean-dir` | If exporting to current directory (default) then all
existing files are preserved. Enabling this option will force cleaning current
directory including all sub dirs (use this with care) | false | boolean
-| `--console` | Developer console at /q/dev on local HTTP server (port 8080 by
default). Camel Main runtime only. | false | boolean
+| `--console` | Developer console on the local HTTP server (port 8080 by
default): /q/dev with Camel Main, /actuator/camel with Spring Boot, and
/q/camel/dev-console with Quarkus. The exported project only has the console
with the dev profile. | false | boolean
| `--cyclonedx-plugin-version` | The CycloneDX Maven Plugin version | 2.9.1 |
String
| `--dep,--dependency` | Add additional dependencies | | List
| `--dir,--directory` | Directory where the project will be exported | . |
String
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-commands-metadata.json
b/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-commands-metadata.json
index 47fcc4d2f6ae..46eaff25cc86 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-commands-metadata.json
+++
b/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-commands-metadata.json
@@ -6,15 +6,15 @@
{ "name": "cmd", "fullName": "cmd", "description": "Performs commands in
the running Camel integrations, such as start\/stop route, or change logging
levels.", "sourceClass":
"org.apache.camel.dsl.jbang.core.commands.action.CamelAction", "options": [ {
"names": "-h,--help", "description": "Display the help and sub-commands",
"javaType": "boolean", "type": "boolean" } ], "subcommands": [ { "name":
"browse", "fullName": "cmd browse", "description": "Browse pending messages on
endpoints [...]
{ "name": "completion", "fullName": "completion", "description": "Generate
completion script for bash\/zsh", "sourceClass":
"org.apache.camel.dsl.jbang.core.commands.Complete", "options": [ { "names":
"-h,--help", "description": "Display the help and sub-commands", "javaType":
"boolean", "type": "boolean" } ] },
{ "name": "config", "fullName": "config", "description": "Get and set user
configuration values", "sourceClass":
"org.apache.camel.dsl.jbang.core.commands.config.ConfigCommand", "options": [ {
"names": "-h,--help", "description": "Display the help and sub-commands",
"javaType": "boolean", "type": "boolean" } ], "subcommands": [ { "name": "get",
"fullName": "config get", "description": "Display user configuration value",
"sourceClass": "org.apache.camel.dsl.jbang.core.commands.config. [...]
- { "name": "debug", "fullName": "debug", "description": "Debug local Camel
integration", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.Debug",
"options": [ { "names": "--ago", "description": "Use ago instead of yyyy-MM-dd
HH:mm:ss in timestamp.", "javaType": "boolean", "type": "boolean" }, { "names":
"--background", "description": "Run in the background", "defaultValue":
"false", "javaType": "boolean", "type": "boolean" }, { "names":
"--background-wait", "description": "To [...]
- { "name": "dependency", "fullName": "dependency", "description": "Displays
all Camel dependencies required to run", "sourceClass":
"org.apache.camel.dsl.jbang.core.commands.DependencyCommand", "options": [ {
"names": "-h,--help", "description": "Display the help and sub-commands",
"javaType": "boolean", "type": "boolean" } ], "subcommands": [ { "name":
"copy", "fullName": "dependency copy", "description": "Copies all Camel
dependencies required to run to a specific directory", "sourc [...]
- { "name": "dev", "fullName": "dev", "description": "Run in dev mode with
live reload", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.Dev",
"options": [ { "names": "--background", "description": "Run in the background",
"defaultValue": "false", "javaType": "boolean", "type": "boolean" }, { "names":
"--background-wait", "description": "To wait for run in background to startup
successfully, before returning", "defaultValue": "true", "javaType": "boolean",
"type": "boolean" }, [...]
+ { "name": "debug", "fullName": "debug", "description": "Debug local Camel
integration", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.Debug",
"options": [ { "names": "--ago", "description": "Use ago instead of yyyy-MM-dd
HH:mm:ss in timestamp.", "javaType": "boolean", "type": "boolean" }, { "names":
"--background", "description": "Run in the background", "defaultValue":
"false", "javaType": "boolean", "type": "boolean" }, { "names":
"--background-wait", "description": "To [...]
+ { "name": "dependency", "fullName": "dependency", "description": "Displays
all Camel dependencies required to run", "sourceClass":
"org.apache.camel.dsl.jbang.core.commands.DependencyCommand", "options": [ {
"names": "-h,--help", "description": "Display the help and sub-commands",
"javaType": "boolean", "type": "boolean" } ], "subcommands": [ { "name":
"copy", "fullName": "dependency copy", "description": "Copies all Camel
dependencies required to run to a specific directory", "sourc [...]
+ { "name": "dev", "fullName": "dev", "description": "Run in dev mode with
live reload", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.Dev",
"options": [ { "names": "--background", "description": "Run in the background",
"defaultValue": "false", "javaType": "boolean", "type": "boolean" }, { "names":
"--background-wait", "description": "To wait for run in background to startup
successfully, before returning", "defaultValue": "true", "javaType": "boolean",
"type": "boolean" }, [...]
{ "name": "dirty", "fullName": "dirty", "description": "Check if there are
dirty files from previous Camel runs that did not terminate gracefully",
"sourceClass": "org.apache.camel.dsl.jbang.core.commands.process.Dirty",
"options": [ { "names": "--clean", "description": "Clean dirty files which are
no longer in use", "defaultValue": "false", "javaType": "boolean", "type":
"boolean" }, { "names": "-h,--help", "description": "Display the help and
sub-commands", "javaType": "boolean", " [...]
{ "name": "doc", "fullName": "doc", "description": "Shows documentation
for kamelet, component, and other Camel resources", "sourceClass":
"org.apache.camel.dsl.jbang.core.commands.catalog.CatalogDoc", "options": [ {
"names": "--camel-version", "description": "To use a different Camel version
than the default version", "javaType": "java.lang.String", "type": "string" },
{ "names": "--download", "description": "Whether to allow automatic downloading
JAR dependencies (over the internet [...]
{ "name": "doctor", "fullName": "doctor", "description": "Checks the
environment and reports potential issues", "sourceClass":
"org.apache.camel.dsl.jbang.core.commands.Doctor", "options": [ { "names":
"-h,--help", "description": "Display the help and sub-commands", "javaType":
"boolean", "type": "boolean" } ] },
{ "name": "eval", "fullName": "eval", "description": "Evaluate Camel
expressions and scripts", "sourceClass":
"org.apache.camel.dsl.jbang.core.commands.EvalCommand", "options": [ { "names":
"-h,--help", "description": "Display the help and sub-commands", "javaType":
"boolean", "type": "boolean" } ], "subcommands": [ { "name": "expression",
"fullName": "eval expression", "description": "Evaluates Camel expression",
"sourceClass": "org.apache.camel.dsl.jbang.core.commands.action.EvalEx [...]
{ "name": "explain", "fullName": "explain", "description": "Explain what a
Camel route does using AI\/LLM", "sourceClass":
"org.apache.camel.dsl.jbang.core.commands.Explain", "options": [ { "names":
"--api-key", "description": "API key for authentication. Also reads
ANTHROPIC_API_KEY, OPENAI_API_KEY, WATSONX_APIKEY, or LLM_API_KEY env vars",
"javaType": "java.lang.String", "type": "string" }, { "names": "--api-type",
"description": "API type: 'ollama', 'openai' (OpenAI-compatible), ' [...]
- { "name": "export", "fullName": "export", "description": "Export to other
runtimes (Camel Main, Spring Boot, or Quarkus)", "sourceClass":
"org.apache.camel.dsl.jbang.core.commands.Export", "options": [ { "names":
"--build-property", "description": "Maven build properties, ex.
--build-property=prop1=foo", "javaType": "java.util.List", "type": "array" }, {
"names": "--camel-spring-boot-version", "description": "Camel version to use
with Spring Boot", "javaType": "java.lang.String", "ty [...]
+ { "name": "export", "fullName": "export", "description": "Export to other
runtimes (Camel Main, Spring Boot, or Quarkus)", "sourceClass":
"org.apache.camel.dsl.jbang.core.commands.Export", "options": [ { "names":
"--build-property", "description": "Maven build properties, ex.
--build-property=prop1=foo", "javaType": "java.util.List", "type": "array" }, {
"names": "--camel-spring-boot-version", "description": "Camel version to use
with Spring Boot", "javaType": "java.lang.String", "ty [...]
{ "name": "get", "fullName": "get", "description": "Get status of Camel
integrations", "sourceClass":
"org.apache.camel.dsl.jbang.core.commands.process.CamelStatus", "options": [ {
"names": "--watch", "description": "Execute periodically and showing output
fullscreen", "javaType": "boolean", "type": "boolean" }, { "names":
"-h,--help", "description": "Display the help and sub-commands", "javaType":
"boolean", "type": "boolean" } ], "subcommands": [ { "name": "activity",
"fullName": " [...]
{ "name": "harden", "fullName": "harden", "description": "Suggest security
hardening for Camel routes using AI\/LLM", "sourceClass":
"org.apache.camel.dsl.jbang.core.commands.Harden", "options": [ { "names":
"--api-key", "description": "API key for authentication. Also reads
OPENAI_API_KEY or LLM_API_KEY env vars", "javaType": "java.lang.String",
"type": "string" }, { "names": "--api-type", "description": "API type: 'ollama'
or 'openai' (OpenAI-compatible)", "defaultValue": "ollama", [...]
{ "name": "hawtio", "fullName": "hawtio", "description": "Launch Hawtio
web console", "sourceClass":
"org.apache.camel.dsl.jbang.core.commands.process.Hawtio", "options": [ {
"names": "--host", "description": "Hostname to bind the Hawtio web console to",
"defaultValue": "127.0.0.1", "javaType": "java.lang.String", "type": "string"
}, { "names": "--openUrl", "description": "To automatic open Hawtio web console
in the web browser", "defaultValue": "true", "javaType": "boolean", "type":
[...]
@@ -26,8 +26,8 @@
{ "name": "plugin", "fullName": "plugin", "description": "Manage plugins
that add sub-commands to this CLI", "sourceClass":
"org.apache.camel.dsl.jbang.core.commands.plugin.PluginCommand", "options": [ {
"names": "-h,--help", "description": "Display the help and sub-commands",
"javaType": "boolean", "type": "boolean" } ], "subcommands": [ { "name": "add",
"fullName": "plugin add", "description": "Add new plugin", "sourceClass":
"org.apache.camel.dsl.jbang.core.commands.plugin.PluginA [...]
{ "name": "ps", "fullName": "ps", "description": "List running Camel
integrations", "sourceClass":
"org.apache.camel.dsl.jbang.core.commands.process.ListProcess", "options": [ {
"names": "--json", "description": "Output in JSON Format", "javaType":
"boolean", "type": "boolean" }, { "names": "--pid", "description": "List only
pid in the output", "javaType": "boolean", "type": "boolean" }, { "names":
"--remote", "description": "Break down counters into remote\/total pairs",
"javaType": [...]
{ "name": "restart", "fullName": "restart", "description": "Restarts
running Camel integrations (stop + re-launch)", "sourceClass":
"org.apache.camel.dsl.jbang.core.commands.process.RestartProcess", "options": [
{ "names": "-h,--help", "description": "Display the help and sub-commands",
"javaType": "boolean", "type": "boolean" } ] },
- { "name": "run", "fullName": "run", "description": "Run as local Camel
integration", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.Run",
"options": [ { "names": "--background", "description": "Run in the background",
"defaultValue": "false", "javaType": "boolean", "type": "boolean" }, { "names":
"--background-wait", "description": "To wait for run in background to startup
successfully, before returning", "defaultValue": "true", "javaType": "boolean",
"type": "boolean" }, { [...]
- { "name": "sbom", "fullName": "sbom", "description": "Generate a CycloneDX
or SPDX SBOM for a specific project", "sourceClass":
"org.apache.camel.dsl.jbang.core.commands.SBOMGenerator", "options": [ {
"names": "--build-property", "description": "Maven build properties, ex.
--build-property=prop1=foo", "javaType": "java.util.List", "type": "array" }, {
"names": "--camel-spring-boot-version", "description": "Camel version to use
with Spring Boot", "javaType": "java.lang.String", "type" [...]
+ { "name": "run", "fullName": "run", "description": "Run as local Camel
integration", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.Run",
"options": [ { "names": "--background", "description": "Run in the background",
"defaultValue": "false", "javaType": "boolean", "type": "boolean" }, { "names":
"--background-wait", "description": "To wait for run in background to startup
successfully, before returning", "defaultValue": "true", "javaType": "boolean",
"type": "boolean" }, { [...]
+ { "name": "sbom", "fullName": "sbom", "description": "Generate a CycloneDX
or SPDX SBOM for a specific project", "sourceClass":
"org.apache.camel.dsl.jbang.core.commands.SBOMGenerator", "options": [ {
"names": "--build-property", "description": "Maven build properties, ex.
--build-property=prop1=foo", "javaType": "java.util.List", "type": "array" }, {
"names": "--camel-spring-boot-version", "description": "Camel version to use
with Spring Boot", "javaType": "java.lang.String", "type" [...]
{ "name": "script", "fullName": "script", "description": "Run Camel
integration as shell script for terminal scripting", "sourceClass":
"org.apache.camel.dsl.jbang.core.commands.Script", "options": [ { "names":
"--logging", "description": "Can be used to turn on logging (logs to file in
<user home>\/.camel directory)", "defaultValue": "false", "javaType":
"boolean", "type": "boolean" }, { "names": "--logging-level", "description":
"Logging level (ERROR, WARN, INFO, DEBUG, TRACE)", "d [...]
{ "name": "shell", "fullName": "shell", "description": "Interactive Camel
CLI shell.", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.Shell",
"options": [ { "names": "-h,--help", "description": "Display the help and
sub-commands", "javaType": "boolean", "type": "boolean" } ] },
{ "name": "stop", "fullName": "stop", "description": "Shuts down running
Camel integrations", "sourceClass":
"org.apache.camel.dsl.jbang.core.commands.process.StopProcess", "options": [ {
"names": "--kill", "description": "To force killing the process (SIGKILL)",
"javaType": "boolean", "type": "boolean" }, { "names": "-h,--help",
"description": "Display the help and sub-commands", "javaType": "boolean",
"type": "boolean" } ] },
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java
index a3bd3cbdb8ea..cf069a12cbab 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java
@@ -226,8 +226,14 @@ public abstract class ExportBaseCommand extends
CamelCommand {
description = "Enable observability services")
protected boolean observe;
+ // set by camel run: the exported project is temporary and only used for
that run, so the developer console is
+ // enabled in its application.properties regardless of the profile
+ boolean consoleForRun;
+
@CommandLine.Option(names = { "--console" }, defaultValue = "false",
- description = "Developer console at /q/dev on local
HTTP server (port 8080 by default). Camel Main runtime only.")
+ description = "Developer console on the local HTTP
server (port 8080 by default): /q/dev with Camel Main,"
+ + " /actuator/camel with Spring Boot,
and /q/camel/dev-console with Quarkus."
+ + " The exported project only has the
console with the dev profile.")
protected boolean console;
@CommandLine.Option(names = {
@@ -1355,6 +1361,73 @@ public abstract class ExportBaseCommand extends
CamelCommand {
return false;
}
+ /**
+ * Whether the developer console ({@code --console}) settings go into the
exported {@code application.properties}:
+ * for {@code camel run} (the project is temporary), and for {@code
--profile=dev} (the dev profile is flattened
+ * into application.properties). Otherwise they go into {@code
application-dev.properties}, so an exported project
+ * only has the console when running with the dev profile.
+ */
+ protected boolean isConsoleInApplicationProperties() {
+ return consoleForRun || "dev".equals(profile);
+ }
+
+ /**
+ * Adds the given developer console settings to the exported project:
either to the given
+ * {@code application.properties} (see {@link
#isConsoleInApplicationProperties()}), or else collected in
+ * {@code devProfile} to be written to {@code application-dev.properties}
by
+ * {@link #writeDevProfileProperties(Path, Map)}. Settings that are
already configured are kept.
+ */
+ protected void addConsoleProperties(Properties prop, Map<String, String>
devProfile, Map<String, String> settings) {
+ for (Map.Entry<String, String> entry : settings.entrySet()) {
+ String key = entry.getKey();
+ if (prop.containsKey(key) ||
prop.containsKey(StringHelper.camelCaseToDash(key))) {
+ continue;
+ }
+ if (isConsoleInApplicationProperties()) {
+ prop.put(key, entry.getValue());
+ } else {
+ devProfile.put(key, entry.getValue());
+ }
+ }
+ }
+
+ /**
+ * Appends the given properties to {@code application-dev.properties} in
the exported project (which is created if
+ * it does not exist), skipping keys that the file already has.
+ */
+ protected void writeDevProfileProperties(Path srcResourcesDir, Map<String,
String> devProfile) throws Exception {
+ if (devProfile.isEmpty()) {
+ return;
+ }
+ Path file = srcResourcesDir.resolve("application-dev.properties");
+ Properties existing = new Properties();
+ if (Files.exists(file)) {
+ try (InputStream is = Files.newInputStream(file)) {
+ existing.load(is);
+ }
+ }
+ StringBuilder sb = new StringBuilder();
+ for (Map.Entry<String, String> entry : devProfile.entrySet()) {
+ String key = entry.getKey();
+ if (existing.containsKey(key) ||
existing.containsKey(StringHelper.camelCaseToDash(key))) {
+ continue;
+ }
+ String line = applicationPropertyLine(key, entry.getValue());
+ if (line != null && !line.isBlank()) {
+ sb.append(line).append("\n");
+ }
+ }
+ if (sb.isEmpty()) {
+ return;
+ }
+ String content = Files.exists(file) ? Files.readString(file) : "";
+ if (!content.isEmpty() && !content.endsWith("\n")) {
+ content += "\n";
+ }
+ content += "# developer console (--console), only for the dev
profile\n" + sb;
+ Files.writeString(file, content);
+ }
+
protected static int httpManagementPort(Path settings) {
try {
List<String> lines = RuntimeUtil.loadPropertiesLines(settings);
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportCamelMain.java
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportCamelMain.java
index fc01b6e35ab7..a9cf94801f7f 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportCamelMain.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportCamelMain.java
@@ -23,6 +23,7 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
@@ -39,7 +40,6 @@ import org.apache.camel.dsl.jbang.core.common.VersionHelper;
import org.apache.camel.tooling.maven.MavenGav;
import org.apache.camel.util.CamelCaseOrderedProperties;
import org.apache.camel.util.ObjectHelper;
-import org.apache.camel.util.StringHelper;
import static
org.apache.camel.dsl.jbang.core.commands.ExportHelper.exportPackageName;
@@ -118,6 +118,7 @@ class ExportCamelMain extends Export {
srcResourcesDir, srcCamelResourcesDir,
srcKameletsResourcesDir, srcPackageName);
// copy from settings to profile
+ Map<String, String> devProfile = new LinkedHashMap<>();
copySettingsAndProfile(settings, profile,
srcResourcesDir, prop -> {
if (groovyPrecompiled &&
!prop.containsKey("camel.main.groovyPreloadCompiled")) {
@@ -160,17 +161,17 @@ class ExportCamelMain extends Export {
// developer console (--console) is configured in-process
by camel-jbang, so export the
// equivalent settings (same as KameletMain: console with
health, info and jolokia)
if (settingsFlag(settings, CamelJBangConstants.CONSOLE)) {
- prop.put("camel.management.enabled", "true");
- for (String key :
List.of("camel.main.devConsoleEnabled", "camel.management.devConsoleEnabled",
- "camel.management.healthCheckEnabled",
"camel.management.infoEnabled",
- "camel.management.jolokiaEnabled")) {
- if (!prop.containsKey(key) &&
!prop.containsKey(StringHelper.camelCaseToDash(key))) {
- prop.put(key, "true");
- }
+ Map<String, String> console = new LinkedHashMap<>();
+ for (String key : List.of("camel.management.enabled",
"camel.main.devConsoleEnabled",
+ "camel.management.devConsoleEnabled",
"camel.management.healthCheckEnabled",
+ "camel.management.infoEnabled",
"camel.management.jolokiaEnabled")) {
+ console.put(key, "true");
}
+ addConsoleProperties(prop, devProfile, console);
}
return prop;
});
+ writeDevProfileProperties(srcResourcesDir, devProfile);
// create main class
createMainClassSource(srcJavaDir, srcPackageName, mainClassname);
// copy local lib JARs
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportQuarkus.java
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportQuarkus.java
index 7da2264a211e..30a1fdbd29e7 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportQuarkus.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportQuarkus.java
@@ -26,6 +26,7 @@ import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
@@ -60,6 +61,7 @@ import org.apache.camel.util.StringHelper;
import static
org.apache.camel.dsl.jbang.core.commands.ExportHelper.exportPackageName;
import static
org.apache.camel.dsl.jbang.core.common.CamelJBangConstants.CLASSPATH_FILES;
+import static
org.apache.camel.dsl.jbang.core.common.CamelJBangConstants.CONSOLE;
class ExportQuarkus extends Export {
@@ -129,6 +131,7 @@ class ExportQuarkus extends Export {
srcResourcesDir, srcCamelResourcesDir,
srcKameletsResourcesDir, srcPackageName);
// copy from settings to profile
+ Map<String, String> devProfile = new LinkedHashMap<>();
copySettingsAndProfile(settings, profile, srcResourcesDir, prop -> {
if (!hasModeline(settings)) {
prop.remove("camel.main.modeline");
@@ -152,8 +155,15 @@ class ExportQuarkus extends Export {
if (hawtio) {
prop.setProperty("quarkus.hawtio.authenticationEnabled",
"false");
}
+ // developer console (--console) is the camel-quarkus-console
extension (/q/camel/dev-console), which
+ // only exposes the console in dev and test mode
(quarkus.camel.console.exposure-mode) so an exported
+ // project has no console in prod mode (camel run sets the
exposure mode for its temporary project)
+ if (settingsFlag(settings, CONSOLE)) {
+ addConsoleProperties(prop, devProfile,
Map.of("camel.main.devConsoleEnabled", "true"));
+ }
return prop;
});
+ writeDevProfileProperties(srcResourcesDir, devProfile);
// copy docker files
if (docker) {
copyDockerFiles(BUILD_DIR);
@@ -512,6 +522,11 @@ class ExportQuarkus extends Export {
answer.add("mvn:org.apache.camel:camel-management");
answer.add("mvn:io.hawt:hawtio-quarkus:" + hawtioVersion);
}
+ if (settingsFlag(settings, CONSOLE)) {
+ // developer console (--console) as the camel-quarkus-console
extension
+ answer.add("mvn:org.apache.camel:camel-console");
+ answer.add("mvn:org.apache.camel:camel-management");
+ }
return answer;
}
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportSpringBoot.java
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportSpringBoot.java
index 42ccfb3e16c0..305b020a6fea 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportSpringBoot.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportSpringBoot.java
@@ -24,7 +24,10 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -32,6 +35,7 @@ import java.util.Properties;
import java.util.Set;
import org.apache.camel.catalog.CamelCatalog;
+import org.apache.camel.dsl.jbang.core.common.CamelJBangConstants;
import org.apache.camel.dsl.jbang.core.common.CatalogLoader;
import org.apache.camel.dsl.jbang.core.common.CommandLineHelper;
import org.apache.camel.dsl.jbang.core.common.PathUtils;
@@ -123,6 +127,7 @@ class ExportSpringBoot extends Export {
// copy local lib JARs
copyLocalLibDependencies(deps);
// copy from settings to profile
+ Map<String, String> devProfile = new LinkedHashMap<>();
copySettingsAndProfile(settings, profile, srcResourcesDir, prop -> {
if (!hasModeline(settings)) {
prop.remove("camel.main.modeline");
@@ -150,18 +155,32 @@ class ExportSpringBoot extends Export {
}
if (hawtio) {
// spring boot needs these options configured to support hawtio
- String s =
prop.getProperty("management.endpoints.web.exposure.include");
- if (s == null) {
- s = "hawtio,jolokia";
- } else {
- s = s + ",hawtio,jolokia";
- }
- prop.setProperty("management.endpoints.web.exposure.include",
s);
+ prop.setProperty("management.endpoints.web.exposure.include",
+
exposeActuatorEndpoints(prop.getProperty("management.endpoints.web.exposure.include"),
+ "hawtio", "jolokia"));
prop.setProperty("spring.jmx.enabled", "true");
prop.setProperty("hawtio.authenticationEnabled", "false");
}
+ // developer console (--console) is the camel actuator endpoint
(/actuator/camel)
+ if (settingsFlag(settings, CamelJBangConstants.CONSOLE)) {
+ addConsoleProperties(prop, devProfile,
Map.of("camel.main.devConsoleEnabled", "true"));
+ // the camel endpoint must be exposed, keeping what is already
exposed as the profile replaces the
+ // value. With --observe the starter exposes health and
prometheus as its default, which an explicit
+ // list would replace, so keep them too (the console is then
at /observe/camel)
+ String exposed =
prop.getProperty("management.endpoints.web.exposure.include");
+ if (exposed == null && observe) {
+ exposed = "health,prometheus";
+ }
+ exposed = exposeActuatorEndpoints(exposed, "camel");
+ if (isConsoleInApplicationProperties()) {
+ prop.put("management.endpoints.web.exposure.include",
exposed);
+ } else {
+
devProfile.put("management.endpoints.web.exposure.include", exposed);
+ }
+ }
return prop;
});
+ writeDevProfileProperties(srcResourcesDir, devProfile);
createMavenPom(settings, profile, buildDir.resolve("pom.xml"), deps);
if (mavenWrapper) {
copyMavenWrapper();
@@ -424,10 +443,36 @@ class ExportSpringBoot extends Export {
String hawtioArtifact = springBootVersion.startsWith("4.") ?
"hawtio-springboot4" : "hawtio-springboot";
answer.add("mvn:io.hawt:" + hawtioArtifact + ":" + hawtioVersion);
}
+ if (settingsFlag(settings, CamelJBangConstants.CONSOLE)) {
+ // developer console (--console) as actuator endpoint
(camel-console-starter)
+ answer.add("mvn:org.apache.camel:camel-console");
+ answer.add("mvn:org.apache.camel:camel-management");
+ }
return answer;
}
+ /**
+ * The value of {@code management.endpoints.web.exposure.include} with the
given actuator endpoint ids added to the
+ * ids that are already exposed (without duplicates).
+ */
+ static String exposeActuatorEndpoints(String exposed, String... ids) {
+ Set<String> answer = new LinkedHashSet<>();
+ if (exposed != null) {
+ if (exposed.contains("*")) {
+ // all endpoints are exposed already
+ return exposed;
+ }
+ for (String id : exposed.split(",")) {
+ if (!id.isBlank()) {
+ answer.add(id.trim());
+ }
+ }
+ }
+ answer.addAll(Arrays.asList(ids));
+ return String.join(",", answer);
+ }
+
private void createMainClassSource(Path srcJavaDir, String packageName,
String mainClassname) throws Exception {
Map<String, Object> model = new HashMap<>();
model.put("PackageName", packageName);
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 33cf67066483..1624a9feb364 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
@@ -1590,6 +1590,9 @@ public class Run extends CamelCommand {
eq.ignoreLoadingError = this.ignoreLoadingError;
eq.lazyBean = this.lazyBean;
eq.profile = this.profile;
+ eq.observe = this.serverOptions.observe;
+ eq.console = this.serverOptions.console;
+ eq.consoleForRun = true;
eq.applicationProperties = this.property;
printer().println("Running using Quarkus (preparing and downloading
files)");
@@ -1631,6 +1634,12 @@ public class Run extends CamelCommand {
if (quarkusRunJvmArgs != null) {
mvnCmd.add("-Djvm.args=" + quarkusRunJvmArgs);
}
+ if (serverOptions.console) {
+ // the console extension only exposes the console in dev and test
mode, and camel run without --dev is
+ // quarkus:run (prod mode). This is build-time configuration, and
is set on the build of this temporary
+ // project only, so an exported project does not have the console
exposed in prod mode
+ mvnCmd.add("-Dquarkus.camel.console.exposure-mode=ALL");
+ }
mvnCmd.add("package");
mvnCmd.add("quarkus:" + (dev ? "dev" : "run"));
pb.command(mvnCmd);
@@ -1766,6 +1775,7 @@ public class Run extends CamelCommand {
eq.profile = this.profile;
eq.observe = this.serverOptions.observe;
eq.console = this.serverOptions.console;
+ eq.consoleForRun = true;
eq.applicationProperties = this.property;
printer().println("Running using Camel Main (preparing and downloading
files)");
@@ -2319,6 +2329,9 @@ public class Run extends CamelCommand {
eq.ignoreLoadingError = this.ignoreLoadingError;
eq.lazyBean = this.lazyBean;
eq.profile = this.profile;
+ eq.observe = this.serverOptions.observe;
+ eq.console = this.serverOptions.console;
+ eq.consoleForRun = true;
eq.applicationProperties = this.property;
printer().println("Running using Spring Boot (preparing and
downloading files)");
@@ -3570,7 +3583,9 @@ public class Run extends CamelCommand {
int managementPort = -1;
@Option(names = { "--console" }, defaultValue = "false",
- description = "Developer console at /q/dev on local HTTP
server (port 8080 by default)")
+ description = "Developer console on the local HTTP server
(port 8080 by default): /q/dev with the jbang"
+ + " and Camel Main runtimes, /actuator/camel
with Spring Boot, and /q/camel/dev-console"
+ + " with Quarkus")
boolean console;
@Option(names = { "--mcp" }, defaultValue = "false",
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ExportTest.java
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ExportTest.java
index 13d28cab8c4f..0596df1a9c49 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ExportTest.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ExportTest.java
@@ -861,8 +861,143 @@ class ExportTest {
containsDependency(model.getDependencies(),
"org.apache.camel", "camel-ai-observability", null));
}
+ @ParameterizedTest
+ @MethodSource("runtimeProvider")
+ public void shouldExportConsoleForDevProfileOnly(RuntimeType rt) throws
Exception {
+ LOG.info("shouldExportConsoleForDevProfileOnly {}", rt);
+ int exit = exportWithConsole(rt);
+
+ Assertions.assertEquals(0, exit);
+ Model model = readMavenModel();
+ assertConsoleDependencies(model, rt);
+
+ // an exported project only has the console with the dev profile
+ Properties props = loadExportedProperties("application.properties");
+ Assertions.assertNull(exportedProperty(props,
"camel.main.devConsoleEnabled"));
+
Assertions.assertNull(props.getProperty("management.endpoints.web.exposure.include"));
+ Assertions.assertNull(props.getProperty("camel.jbang.console"));
+
+ Properties dev = loadExportedProperties("application-dev.properties");
+
Assertions.assertNull(dev.getProperty("quarkus.camel.console.exposure-mode"));
+ // what the application sees with the dev profile active
+ Properties effective = new Properties();
+ effective.putAll(props);
+ effective.putAll(dev);
+ assertConsoleProperties(effective, rt);
+ }
+
+ @ParameterizedTest
+ @MethodSource("runtimeProvider")
+ public void shouldExportConsoleInDevProfileExport(RuntimeType rt) throws
Exception {
+ LOG.info("shouldExportConsoleInDevProfileExport {}", rt);
+ int exit = exportWithConsole(rt, "--profile=dev");
+
+ Assertions.assertEquals(0, exit);
+ Model model = readMavenModel();
+ assertConsoleDependencies(model, rt);
+
+ // the dev profile is flattened into application.properties, and so is
the console
+ Properties props = loadExportedProperties("application.properties");
+ assertConsoleProperties(props, rt);
+
Assertions.assertNull(props.getProperty("quarkus.camel.console.exposure-mode"));
+ Assertions.assertNull(props.getProperty("camel.jbang.console"));
+ Assertions.assertFalse(new File(workingDir,
"src/main/resources/application-dev.properties").exists());
+ }
+
+ private int exportWithConsole(RuntimeType rt, String... extraArgs) throws
Exception {
+ Export command = new Export(new CamelJBangMain());
+ List<String> cmdArgs = new ArrayList<>(
+ List.of("--gav=examples:route:1.0.0", "--dir=" + workingDir,
"--quiet",
+ "--runtime=%s".formatted(rt.runtime()), "--console"));
+ if (rt == RuntimeType.springBoot) {
+ cmdArgs.add("--camel-version=" + RELEASED_CAMEL_VERSION);
+ }
+ cmdArgs.addAll(List.of(extraArgs));
+ cmdArgs.add("target/test-classes/route.yaml");
+ CommandLine.populateCommand(command, cmdArgs.toArray(String[]::new));
+ return command.doCall();
+ }
+
+ private Properties loadExportedProperties(String name) throws Exception {
+ Properties props = new Properties();
+ File f = new File(workingDir, "src/main/resources/" + name);
+ Assertions.assertTrue(f.isFile(), "Missing " + name);
+ try (FileInputStream fis = new FileInputStream(f)) {
+ props.load(fis);
+ }
+ return props;
+ }
+
+ private void assertConsoleDependencies(Model model, RuntimeType rt) {
+ if (rt == RuntimeType.main) {
+ for (String artifact : List.of("camel-console",
"camel-management", "camel-health",
+ "camel-platform-http-main",
"camel-platform-http-jolokia")) {
+
Assertions.assertTrue(containsDependency(model.getDependencies(),
"org.apache.camel", artifact, null),
+ "Missing dependency " + artifact);
+ }
+ } else if (rt == RuntimeType.springBoot) {
+ for (String artifact : List.of("camel-console-starter",
"camel-management-starter")) {
+ Assertions.assertTrue(
+ containsDependency(model.getDependencies(),
"org.apache.camel.springboot", artifact, null),
+ "Missing dependency " + artifact);
+ }
+ } else if (rt == RuntimeType.quarkus) {
+ for (String artifact : List.of("camel-quarkus-console",
"camel-quarkus-management")) {
+ Assertions.assertTrue(
+ containsDependency(model.getDependencies(),
"org.apache.camel.quarkus", artifact, null),
+ "Missing dependency " + artifact);
+ }
+ }
+ }
+
+ private static void assertConsoleProperties(Properties props, RuntimeType
rt) {
+ // the developer console is enabled with the same camel-main option on
all runtimes
+ Assertions.assertEquals("true", exportedProperty(props,
"camel.main.devConsoleEnabled"));
+ if (rt == RuntimeType.main) {
+ for (String key : List.of("camel.management.enabled",
"camel.management.devConsoleEnabled",
+ "camel.management.healthCheckEnabled",
"camel.management.infoEnabled",
+ "camel.management.jolokiaEnabled")) {
+ Assertions.assertEquals("true", exportedProperty(props, key),
"Missing property " + key);
+ }
+ } else if (rt == RuntimeType.springBoot) {
+ // the console is the camel actuator endpoint, which must be
exposed over the web
+ Assertions.assertEquals("camel",
props.getProperty("management.endpoints.web.exposure.include"));
+ }
+ }
+
@Test
- public void shouldExportConsoleForCamelMain() throws Exception {
+ public void shouldExposeConsoleWithObserveOnSpringBoot() throws Exception {
+ int exit = exportWithConsole(RuntimeType.springBoot, "--observe");
+
+ Assertions.assertEquals(0, exit);
+ // the observability defaults must survive the explicit exposure list
+ Properties dev = loadExportedProperties("application-dev.properties");
+ Assertions.assertEquals("health,prometheus,camel",
dev.getProperty("management.endpoints.web.exposure.include"));
+ }
+
+ @Test
+ public void shouldExposeConsoleWithHawtioOnSpringBoot() throws Exception {
+ int exit = exportWithConsole(RuntimeType.springBoot, "--hawtio");
+
+ Assertions.assertEquals(0, exit);
+ // hawtio is exposed in application.properties, and the dev profile
must keep it when adding the console
+ Properties props = loadExportedProperties("application.properties");
+ Assertions.assertEquals("hawtio,jolokia",
props.getProperty("management.endpoints.web.exposure.include"));
+ Properties dev = loadExportedProperties("application-dev.properties");
+ Assertions.assertEquals("hawtio,jolokia,camel",
dev.getProperty("management.endpoints.web.exposure.include"));
+ }
+
+ @Test
+ public void shouldNotDuplicateExposedActuatorEndpoints() {
+ Assertions.assertEquals("camel",
ExportSpringBoot.exposeActuatorEndpoints(null, "camel"));
+ Assertions.assertEquals("health,camel",
ExportSpringBoot.exposeActuatorEndpoints("health, camel", "camel"));
+ Assertions.assertEquals("hawtio,jolokia,camel",
+ ExportSpringBoot.exposeActuatorEndpoints("hawtio,jolokia",
"hawtio", "jolokia", "camel"));
+ Assertions.assertEquals("*",
ExportSpringBoot.exposeActuatorEndpoints("*", "camel"));
+ }
+
+ @Test
+ public void shouldAppendConsoleToExistingDevProfile() throws Exception {
Export command = new Export(new CamelJBangMain());
CommandLine.populateCommand(command,
"--gav=examples:route:1.0.0",
@@ -870,28 +1005,14 @@ class ExportTest {
"--quiet",
"--runtime=main",
"--console",
- "target/test-classes/route.yaml");
+ "src/test/resources/devprofile");
int exit = command.doCall();
Assertions.assertEquals(0, exit);
- Model model = readMavenModel();
- for (String artifact : List.of("camel-console", "camel-management",
"camel-health",
- "camel-platform-http-main", "camel-platform-http-jolokia")) {
- Assertions.assertTrue(containsDependency(model.getDependencies(),
"org.apache.camel", artifact, null),
- "Missing dependency " + artifact);
- }
-
- Properties props = new Properties();
- try (FileInputStream fis = new FileInputStream(new File(workingDir,
"src/main/resources/application.properties"))) {
- props.load(fis);
- }
- for (String key : List.of("camel.main.devConsoleEnabled",
"camel.management.enabled",
- "camel.management.devConsoleEnabled",
"camel.management.healthCheckEnabled",
- "camel.management.infoEnabled",
"camel.management.jolokiaEnabled")) {
- Assertions.assertEquals("true", exportedProperty(props, key),
"Missing property " + key);
- }
- // internal camel-jbang settings must not leak into the exported
project
- Assertions.assertNull(props.getProperty("camel.jbang.console"));
+ Properties dev = loadExportedProperties("application-dev.properties");
+ // the user's own dev profile settings are kept
+ Assertions.assertEquals("true", dev.getProperty("camel.main.tracing"));
+ Assertions.assertEquals("true", exportedProperty(dev,
"camel.main.devConsoleEnabled"));
}
@Test
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/devprofile/application-dev.properties
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/devprofile/application-dev.properties
new file mode 100644
index 000000000000..b755bba111a4
--- /dev/null
+++
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/devprofile/application-dev.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.
+## ---------------------------------------------------------------------------
+camel.main.tracing=true
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/devprofile/hello.yaml
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/devprofile/hello.yaml
new file mode 100644
index 000000000000..d3b7b551a7f8
--- /dev/null
+++ b/dsl/camel-jbang/camel-jbang-core/src/test/resources/devprofile/hello.yaml
@@ -0,0 +1,28 @@
+#
+# 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.
+#
+
+# camel-k: language=yaml
+
+# Write your routes here, for example:
+- from:
+ uri: "timer:yaml"
+ parameters:
+ period: "1000"
+ steps:
+ - setBody:
+ constant: "Hello Camel from yaml"
+ - log: "${body}"