This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch fix/CAMEL-24661-console in repository https://gitbox.apache.org/repos/asf/camel.git
commit fc34ab32071443af0c0f50a9563d44a9a040f075 Author: Claus Ibsen <[email protected]> AuthorDate: Thu Sep 17 10:13:56 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. The Spring Boot export now adds camel-console-starter (the camel actuator endpoint at /actuator/camel) and exposes it, keeping health and prometheus exposed when --observe is also used (the console is then at /observe/camel on the management port). The Quarkus export adds the camel-quarkus-console extension (/q/camel/dev-console) and sets exposure-mode=ALL as camel run without --dev runs via quarkus:run in prod mode. The console is enabled with the shared camel.main.devConsoleEnabled option on all runtimes. camel run --runtime=quarkus|spring-boot also did not pass --observe and --console on to the exporter at all; only the Camel Main run did. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Signed-off-by: Claus Ibsen <[email protected]> --- .../modules/ROOT/pages/camel-jbang-managing.adoc | 7 ++ .../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 | 3 +- .../dsl/jbang/core/commands/ExportQuarkus.java | 18 +++++ .../dsl/jbang/core/commands/ExportSpringBoot.java | 41 ++++++++-- .../apache/camel/dsl/jbang/core/commands/Run.java | 8 +- .../camel/dsl/jbang/core/commands/ExportTest.java | 94 ++++++++++++++++++---- 16 files changed, 165 insertions(+), 42 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..2f3c5b94536b 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,13 @@ 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: `/q/dev` with Camel Main, `/actuator/camel` with Spring Boot (the `camel` actuator +endpoint; with `--observe` it moves to the management port under `/observe/camel`), and +`/q/camel/dev-console` with Quarkus. The exported Quarkus project exposes the console in prod mode +(`quarkus.camel.console.exposure-mode=ALL`) as `camel run` without `--dev` runs via `quarkus:run`. The +console has no authentication on any runtime, so it is meant for local development only. + 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..5aa33e5b1701 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 | 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..5eefd596dfcc 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 | 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..468e917ed9fa 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 | 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..af05d379d80c 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 | 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..13c4d839acfc 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 | 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..445903276915 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..40903035882b 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 @@ -227,7 +227,8 @@ public abstract class ExportBaseCommand extends CamelCommand { protected boolean observe; @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") protected boolean console; @CommandLine.Option(names = { 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..ce5e54eb588e 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 @@ -60,6 +60,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 { @@ -152,6 +153,18 @@ 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) + if (settingsFlag(settings, CONSOLE)) { + if (!prop.containsKey("camel.main.devConsoleEnabled") + && !prop.containsKey("camel.main.dev-console-enabled")) { + prop.put("camel.main.devConsoleEnabled", "true"); + } + // the console is only exposed in dev and test mode by default, and camel run without --dev runs in + // prod mode (quarkus:run). The console has no authentication, so this is for local development only. + if (!prop.containsKey("quarkus.camel.console.exposure-mode")) { + prop.put("quarkus.camel.console.exposure-mode", "ALL"); + } + } return prop; }); // copy docker files @@ -512,6 +525,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..da1bec69d1af 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 @@ -32,6 +32,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; @@ -150,16 +151,23 @@ 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); + exposeActuatorEndpoints(prop, "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)) { + if (!prop.containsKey("camel.main.devConsoleEnabled") + && !prop.containsKey("camel.main.dev-console-enabled")) { + prop.put("camel.main.devConsoleEnabled", "true"); + } + if (observe && !prop.containsKey("management.endpoints.web.exposure.include")) { + // camel-observability-services-starter exposes health and prometheus as its default, which an + // explicit exposure list would replace, so keep them (the console is then at /observe/camel) + exposeActuatorEndpoints(prop, "health,prometheus"); + } + exposeActuatorEndpoints(prop, "camel"); + } return prop; }); createMavenPom(settings, profile, buildDir.resolve("pom.xml"), deps); @@ -424,10 +432,29 @@ 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; } + /** + * Adds the given actuator endpoint ids to {@code management.endpoints.web.exposure.include}, keeping the ids that + * are already exposed. + */ + private static void exposeActuatorEndpoints(Properties prop, String ids) { + String s = prop.getProperty("management.endpoints.web.exposure.include"); + if (s == null || s.isBlank()) { + s = ids; + } else { + s = s + "," + ids; + } + prop.setProperty("management.endpoints.web.exposure.include", s); + } + 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..0f3c07456f30 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,8 @@ 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.applicationProperties = this.property; printer().println("Running using Quarkus (preparing and downloading files)"); @@ -2319,6 +2321,8 @@ 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.applicationProperties = this.property; printer().println("Running using Spring Boot (preparing and downloading files)"); @@ -3570,7 +3574,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..d79c259aaa9e 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,37 +861,101 @@ class ExportTest { containsDependency(model.getDependencies(), "org.apache.camel", "camel-ai-observability", null)); } + @ParameterizedTest + @MethodSource("runtimeProvider") + public void shouldExportConsole(RuntimeType rt) throws Exception { + LOG.info("shouldExportConsole {}", rt); + 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.add("target/test-classes/route.yaml"); + CommandLine.populateCommand(command, cmdArgs.toArray(String[]::new)); + int exit = command.doCall(); + + Assertions.assertEquals(0, exit); + Model model = readMavenModel(); + Properties props = new Properties(); + try (FileInputStream fis = new FileInputStream(new File(workingDir, "src/main/resources/application.properties"))) { + props.load(fis); + } + // the developer console is enabled with the same camel-main option on all runtimes + Assertions.assertEquals("true", exportedProperty(props, "camel.main.devConsoleEnabled")); + // internal camel-jbang settings must not leak into the exported project + Assertions.assertNull(props.getProperty("camel.jbang.console")); + + 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); + } + 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 + 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); + } + Assertions.assertEquals("camel", props.getProperty("management.endpoints.web.exposure.include")); + } else if (rt == RuntimeType.quarkus) { + // the console extension only exposes the console in dev and test mode unless told otherwise + 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); + } + Assertions.assertEquals("ALL", props.getProperty("quarkus.camel.console.exposure-mode")); + } + } + @Test - public void shouldExportConsoleForCamelMain() throws Exception { + public void shouldExposeConsoleWithObserveOnSpringBoot() throws Exception { Export command = new Export(new CamelJBangMain()); CommandLine.populateCommand(command, "--gav=examples:route:1.0.0", "--dir=" + workingDir, "--quiet", - "--runtime=main", - "--console", + "--runtime=spring-boot", "--camel-version=" + RELEASED_CAMEL_VERSION, + "--console", "--observe", "target/test-classes/route.yaml"); 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); } + // the observability defaults must survive the explicit exposure list + Assertions.assertEquals("health,prometheus,camel", props.getProperty("management.endpoints.web.exposure.include")); + } + @Test + public void shouldExposeConsoleWithHawtioOnSpringBoot() throws Exception { + Export command = new Export(new CamelJBangMain()); + CommandLine.populateCommand(command, + "--gav=examples:route:1.0.0", + "--dir=" + workingDir, + "--quiet", + "--runtime=spring-boot", "--camel-version=" + RELEASED_CAMEL_VERSION, + "--console", "--hawtio", + "target/test-classes/route.yaml"); + int exit = command.doCall(); + + Assertions.assertEquals(0, exit); 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")); + Assertions.assertEquals("hawtio,jolokia,camel", props.getProperty("management.endpoints.web.exposure.include")); } @Test
