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 a6021a32bc4a CAMEL-26930: camel-jbang - camel run options given on the 
command line win over application.properties (#29916)
a6021a32bc4a is described below

commit a6021a32bc4ab774c19bf5ddcc06af35b3005e43
Author: Claus Ibsen <[email protected]>
AuthorDate: Sat Nov 14 19:23:34 2026 +0100

    CAMEL-26930: camel-jbang - camel run options given on the command line win 
over application.properties (#29916)
    
    For most camel run options the same setting in application.properties won: 
with
    camel.main.tracing=false in the file, --trace printed nothing, and with
    camel.jbang.console=false, --console started no console. CAMEL-24705 had 
moved only
    --max-* and --port to the override path.
    
    Run records the options given on the command line in the run request. Where 
the
    settings are taken (RunProfileProperties.applyTo, RunPipeline.configure, the
    logging options of Run), a given option wins over the file, which stays the
    default for the options not given. A given option is set as an initial 
property,
    which KameletMain reads, and as an override property, so camel-main does 
not take
    the file over it. --background and --jvm-debug follow after #29910.
    
    CAMEL-26930: camel-jbang - --background, --background-wait and --jvm-debug 
given on the command line win over application.properties too
    
    Co-Authored-By: Claude Opus 5.5 <[email protected]>
---
 .../ROOT/pages/camel-4x-upgrade-guide-4_24.adoc    | 11 ++++
 .../modules/ROOT/pages/camel-jbang-running.adoc    |  5 ++
 .../dsl/jbang/core/commands/CamelCommand.java      | 18 +++++++
 .../apache/camel/dsl/jbang/core/commands/Run.java  | 33 ++++++++----
 .../camel/dsl/jbang/core/commands/RunTest.java     | 43 +++++++++++++++
 .../test/resources/golden/expected/openapi.run.txt |  1 +
 .../test/resources/golden/expected/options.run.txt |  2 +
 .../resources/golden/expected/run-options.run.txt  |  3 ++
 .../resources/golden/expected/source-dir.run.txt   |  1 +
 .../resources/golden/expected/stub-all.run.txt     |  1 +
 .../resources/golden/expected/stub-names.run.txt   |  1 +
 .../apache/camel/dsl/jbang/run/RunPipeline.java    | 56 +++++++++++++-------
 .../camel/dsl/jbang/run/RunProfileProperties.java  | 45 ++++++++++------
 .../org/apache/camel/dsl/jbang/run/RunRequest.java | 11 ++++
 .../camel/dsl/jbang/run/RunPipelineTest.java       | 61 ++++++++++++++++++++++
 15 files changed, 244 insertions(+), 48 deletions(-)

diff --git 
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc 
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
index 29d263a043d3..910293f7c017 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
@@ -1597,6 +1597,17 @@ The producer no longer reads the 
`CamelOaimphIgnoreSSLWarnings` header, and the
 constant is removed. Use the `ignoreSSLWarnings` option of the endpoint 
instead; when only some repositories need it,
 send to them through an endpoint URI that sets the option.
 
+=== camel-jbang - camel run options win over application.properties
+
+An option given to `camel run` on the command line now wins over the same 
setting in `application.properties`. Before,
+the file won for most options: with `camel.main.tracing=false` in the file, 
`--trace` printed nothing, and with
+`camel.jbang.console=false`, `--console` had no effect. This applies to 
`--trace`, `--backlog-trace`, `--console`,
+`--health`, `--metrics`, `--mcp`, `--openapi-ui`, `--stub`, `--modeline`, 
`--ignore-loading-error`, `--lazy-bean`,
+`--prompt`, `--gav`, `--open-api`, `--verbose`, `--jfr`, `--source-dir`, 
`--data-dir`, `--exclude`,
+`--camel-version`, `--kamelets-version`, `--java-version`, `--background`, 
`--background-wait`, `--jvm-debug`, the
+Maven settings options and the logging options. An
+option that is not given still takes its value from the file.
+
 === camel-clickhouse - a query in a binary format returns a byte[] body
 
 A `query` with a binary `format` (such as `RowBinary`, `Native`, `Parquet`, 
`Arrow` or `Avro`) now returns the result
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 97f3ebd9f316..6e09557b30b3 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-jbang-running.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-jbang-running.adoc
@@ -150,6 +150,11 @@ NOTE: Use the `=` sign directly after `--property` (no 
space).
 
 If both are used, the properties are merged into a single 
`application.properties` file.
 
+The options of `camel run` can also be set in `application.properties`, such 
as `camel.main.tracing=true` for
+`--trace` or `camel.jbang.console=true` for `--console`. An option given on 
the command line wins over the file,
+which is the default for the options that are not given: with 
`camel.main.tracing=false` in the file,
+`camel run --trace` traces.
+
 [#_using_profiles]
 == Using profiles
 
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelCommand.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelCommand.java
index 2deb0cd83c4e..b0ddd85fe223 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelCommand.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelCommand.java
@@ -18,9 +18,11 @@ package org.apache.camel.dsl.jbang.core.commands;
 
 import java.nio.file.Path;
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Optional;
 import java.util.Properties;
+import java.util.Set;
 
 import org.aesh.command.Command;
 import org.aesh.command.CommandResult;
@@ -168,6 +170,22 @@ public abstract class CamelCommand implements 
Command<CommandInvocation>, Comman
         return holder != null ? option.getFieldValue(holder) : null;
     }
 
+    /**
+     * The names of the options given on the command line (without {@code 
--}), such as {@code trace}; empty when the
+     * command was not parsed by aesh.
+     */
+    protected Set<String> givenOptions() {
+        Set<String> answer = new HashSet<>();
+        if (processedCommand != null) {
+            for (ProcessedOption option : processedCommand.getOptions()) {
+                if (!option.getValues().isEmpty()) {
+                    answer.add(option.name());
+                }
+            }
+        }
+        return answer;
+    }
+
     /**
      * Whether an option was given on the command line, rather than having its 
default value.
      */
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 adf12f6e150f..67ae5ba0551a 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
@@ -1076,6 +1076,8 @@ public class Run extends CamelCommand implements 
CommandLifecycle {
      */
     RunRequest toRunRequest(Path baseDir) {
         RunRequest request = new RunRequest();
+        // the options given on the command line win over the application 
properties
+        request.givenOptions = givenOptions();
         request.workDir = workDir;
         request.baseDir = baseDir;
         request.files = files;
@@ -1168,14 +1170,18 @@ public class Run extends CamelCommand implements 
CommandLifecycle {
      */
     void applyProfileProperties(RunRequest request, Properties answer) {
         if (answer != null) {
-            // logging level/color may be configured in the properties file
-            loggingOptions.loggingLevel = answer.getProperty("loggingLevel", 
loggingOptions.loggingLevel);
-            loggingOptions.loggingColor
-                    = "true"
-                            .equals(answer.getProperty("loggingColor", 
loggingOptions.loggingColor ? "true" : "false"));
-            loggingOptions.loggingJson
-                    = "true"
-                            .equals(answer.getProperty("loggingJson", 
loggingOptions.loggingJson ? "true" : "false"));
+            // logging level/color may be configured in the properties file, 
unless given on the command line
+            if (!request.given("logging-level")) {
+                loggingOptions.loggingLevel = 
answer.getProperty("loggingLevel", loggingOptions.loggingLevel);
+            }
+            if (!request.given("logging-color")) {
+                loggingOptions.loggingColor = "true"
+                        .equals(answer.getProperty("loggingColor", 
loggingOptions.loggingColor ? "true" : "false"));
+            }
+            if (!request.given("logging-json")) {
+                loggingOptions.loggingJson = "true"
+                        .equals(answer.getProperty("loggingJson", 
loggingOptions.loggingJson ? "true" : "false"));
+            }
         }
         if (answer != null) {
             mavenResolver = MavenResolverMixin.of(answer, mavenResolver);
@@ -1187,12 +1193,17 @@ public class Run extends CamelCommand implements 
CommandLifecycle {
             // a JVM this command started runs the integration itself: the 
properties must not make it start
             // another JVM, in the background or with a debugger, and that one 
another, without end
             if (!spawned) {
-                background = "true".equals(answer.getProperty(BACKGROUND, 
background ? "true" : "false"));
+                // and an option given on the command line wins over the file
+                if (!request.given("background")) {
+                    background = "true".equals(answer.getProperty(BACKGROUND, 
background ? "true" : "false"));
+                }
                 String wait = answer.getProperty(BACKGROUND_WAIT);
-                if (wait != null) {
+                if (wait != null && !request.given("background-wait")) {
                     backgroundWait = BackgroundWait.parse(wait);
                 }
-                jvmDebugPort = parseJvmDebugPort(answer.getProperty(JVM_DEBUG, 
Integer.toString(jvmDebugPort)));
+                if (!request.given("jvm-debug")) {
+                    jvmDebugPort = 
parseJvmDebugPort(answer.getProperty(JVM_DEBUG, 
Integer.toString(jvmDebugPort)));
+                }
             }
         }
         // what this command reads itself to run in another JVM (with another 
Camel version)
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/RunTest.java
 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/RunTest.java
index 8a551bb9e415..b354e9b0b992 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/RunTest.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/RunTest.java
@@ -268,6 +268,35 @@ class RunTest extends CamelCommandBaseTestSupport {
         assertThat(request.dev).isTrue();
     }
 
+    @Test
+    void theRequestKnowsTheOptionsGivenOnTheCommandLine() {
+        Run command = new Run(new CamelJBangMain());
+        CommandLineTestHelper.parse(command, "--trace", "--console", 
"--logging-level=DEBUG", "--camel-version=4.23.0",
+                "route.yaml");
+
+        RunRequest request = command.toRunRequest(Path.of("."));
+
+        assertThat(request.givenOptions).contains("trace", "console", 
"logging-level", "camel-version")
+                .doesNotContain("health", "metrics", "stub");
+        assertThat(request.given("trace")).isTrue();
+        assertThat(request.given("health")).isFalse();
+    }
+
+    @Test
+    void 
theLoggingOptionsGivenOnTheCommandLineWinOverTheApplicationProperties() {
+        Run command = new Run(new CamelJBangMain());
+        CommandLineTestHelper.parse(command, "--logging-level=DEBUG", 
"route.yaml");
+        Properties properties = new Properties();
+        properties.setProperty("loggingLevel", "WARN");
+        properties.setProperty("loggingJson", "true");
+
+        command.applyProfileProperties(command.toRunRequest(null), properties);
+
+        assertThat(command.loggingOptions.loggingLevel).isEqualTo("DEBUG");
+        // not given: the file
+        assertThat(command.loggingOptions.loggingJson).isTrue();
+    }
+
     @Test
     void theBackgroundAndDebugPropertiesStartAnotherJvm() {
         Run command = new Run(new CamelJBangMain());
@@ -305,6 +334,20 @@ class RunTest extends CamelCommandBaseTestSupport {
         assertThat(pb.environment()).containsEntry(Run.SPAWNED_RUN, "true");
     }
 
+    @Test
+    void 
theBackgroundAndDebugOptionsGivenOnTheCommandLineWinOverTheProperties() {
+        Run command = new Run(new CamelJBangMain());
+        CommandLineTestHelper.parse(command, "--background-wait=1000", 
"--jvm-debug=5005", "route.yaml");
+        command.spawned = false;
+
+        command.applyProfileProperties(command.toRunRequest(null), 
backgroundAndDebugProperties());
+
+        assertThat(command.backgroundWait).isEqualTo(1000);
+        assertThat(command.jvmDebugPort).isEqualTo(5005);
+        // not given: the file
+        assertThat(command.background).isTrue();
+    }
+
     private static Properties backgroundAndDebugProperties() {
         Properties properties = new Properties();
         properties.setProperty("camel.jbang.background", "true");
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/openapi.run.txt
 
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/openapi.run.txt
index 5d368f5ce39d..bfc6c20ad7dc 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/openapi.run.txt
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/openapi.run.txt
@@ -43,3 +43,4 @@ camel.main.name=greeting
 
camel.main.routesIncludePattern=file:${dir}/generated-openapi.yaml,file:src/test/resources/golden/openapi/greeting.camel.yaml
 
 # override properties
+camel.jbang.openApi=src/test/resources/golden/openapi/api.yaml
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/options.run.txt
 
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/options.run.txt
index 7496eae37763..d568a42f1bae 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/options.run.txt
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/options.run.txt
@@ -47,6 +47,8 @@ 
camel.main.routesIncludePattern=file:src/test/resources/golden/options/hello.cam
 camel.server.enabled=true
 
 # override properties
+camel.jbang.console=true
+camel.jbang.gav=com.acme:golden:2.0
 camel.management.port=9191
 camel.metrics.logMetricsOnShutdown=false
 camel.server.port=8181
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/run-options.run.txt
 
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/run-options.run.txt
index b03228ed84b0..3b02eeb16e35 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/run-options.run.txt
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/run-options.run.txt
@@ -54,5 +54,8 @@ camel.main.tracing=true
 camel.trace.enabled=true
 
 # override properties
+camel.jbang.jfr=jfr
 camel.main.durationMaxMessages=5
 camel.main.durationMaxSeconds=60
+camel.main.tracing=true
+camel.trace.enabled=true
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/source-dir.run.txt
 
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/source-dir.run.txt
index 989a8aed9225..380f6167bfb0 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/source-dir.run.txt
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/source-dir.run.txt
@@ -43,3 +43,4 @@ camel.main.name=source-dir
 
camel.main.routesIncludePattern=file:src/test/resources/golden/sourcedir/routes/**?optional=true
 
 # override properties
+camel.jbang.sourceDir=src/test/resources/golden/sourcedir/routes
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/stub-all.run.txt
 
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/stub-all.run.txt
index 4313e9e117b1..85d28d148070 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/stub-all.run.txt
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/stub-all.run.txt
@@ -41,3 +41,4 @@ camel.main.name=hello
 
camel.main.routesIncludePattern=file:src/test/resources/golden/yaml/hello.camel.yaml
 
 # override properties
+camel.jbang.stub=component:*
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/stub-names.run.txt
 
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/stub-names.run.txt
index bd3ab6efe6dc..f88153db9ff1 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/stub-names.run.txt
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/stub-names.run.txt
@@ -41,3 +41,4 @@ camel.main.name=hello
 
camel.main.routesIncludePattern=file:src/test/resources/golden/yaml/hello.camel.yaml
 
 # override properties
+camel.jbang.stub=component:log*,timer:hello
diff --git 
a/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/RunPipeline.java
 
b/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/RunPipeline.java
index a55162d5790c..44b083d99af9 100644
--- 
a/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/RunPipeline.java
+++ 
b/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/RunPipeline.java
@@ -427,7 +427,7 @@ public class RunPipeline {
                 stub = sj.toString();
             }
             request.stub = stub;
-            writeSetting(main, profileProperties, STUB, stub);
+            writeOption(main, profileProperties, "stub", STUB, stub);
             main.setStubPattern(stub);
         }
 
@@ -437,48 +437,48 @@ public class RunPipeline {
             writeSetting(main, profileProperties, 
"camel.main.shutdownTimeout", "5");
         }
         if (request.sourceDir != null) {
-            writeSetting(main, profileProperties, SOURCE_DIR, 
request.sourceDir);
+            writeOption(main, profileProperties, "source-dir", SOURCE_DIR, 
request.sourceDir);
         }
         if (request.dataDir != null) {
-            writeSetting(main, profileProperties, DATA_DIR, request.dataDir);
+            writeOption(main, profileProperties, "data-dir", DATA_DIR, 
request.dataDir);
         }
         if (request.trace) {
-            writeSetting(main, profileProperties, "camel.main.tracing", 
"true");
+            writeOption(main, profileProperties, "trace", 
"camel.main.tracing", "true");
         }
         if (request.backlogTrace) {
-            writeSetting(main, profileProperties, "camel.trace.enabled", 
"true");
+            writeOption(main, profileProperties, "backlog-trace", 
"camel.trace.enabled", "true");
         }
         if (request.modeline) {
-            writeSetting(main, profileProperties, "camel.main.modeline", 
"true");
+            writeOption(main, profileProperties, "modeline", 
"camel.main.modeline", "true");
             // configure eager
             main.configure().withModeline(true);
         }
         if (request.ignoreLoadingError) {
-            writeSetting(main, profileProperties, IGNORE_LOADING_ERROR, 
"true");
+            writeOption(main, profileProperties, "ignore-loading-error", 
IGNORE_LOADING_ERROR, "true");
         }
         if (request.lazyBean) {
-            writeSetting(main, profileProperties, LAZY_BEAN, "true");
+            writeOption(main, profileProperties, "lazy-bean", LAZY_BEAN, 
"true");
         }
         if (request.prompt) {
-            writeSetting(main, profileProperties, PROMPT, "true");
+            writeOption(main, profileProperties, "prompt", PROMPT, "true");
         }
         writeSetting(main, profileProperties, COMPILE_WORK_DIR, 
request.workDir.resolve("compile").toString());
 
         if (request.gav != null) {
-            writeSetting(main, profileProperties, GAV, request.gav);
+            writeOption(main, profileProperties, "gav", GAV, request.gav);
         }
-        writeSetting(main, profileProperties, OPEN_API, request.openapi);
+        writeOption(main, profileProperties, "open-api", OPEN_API, 
request.openapi);
         if (request.mavenResolver != null) {
             request.mavenResolver.putTo((k, v) -> {
                 writeSetting(main, profileProperties, k, v);
             });
         }
-        writeSetting(main, profileProperties, HEALTH, request.health ? "true" 
: "false");
-        writeSetting(main, profileProperties, METRICS, request.metrics ? 
"true" : "false");
-        writeSetting(main, profileProperties, CONSOLE, request.console ? 
"true" : "false");
-        writeSetting(main, profileProperties, MCP, request.mcp ? "true" : 
"false");
-        writeSetting(main, profileProperties, OPENAPI_UI, request.openapiUi ? 
"true" : "false");
-        writeSetting(main, profileProperties, VERBOSE, request.verbose ? 
"true" : "false");
+        writeOption(main, profileProperties, "health", HEALTH, request.health 
? "true" : "false");
+        writeOption(main, profileProperties, "metrics", METRICS, 
request.metrics ? "true" : "false");
+        writeOption(main, profileProperties, "console", CONSOLE, 
request.console ? "true" : "false");
+        writeOption(main, profileProperties, "mcp", MCP, request.mcp ? "true" 
: "false");
+        writeOption(main, profileProperties, "openapi-ui", OPENAPI_UI, 
request.openapiUi ? "true" : "false");
+        writeOption(main, profileProperties, "verbose", VERBOSE, 
request.verbose ? "true" : "false");
         // the runtime version of Camel is what is loaded via the catalog
         writeSetting(main, profileProperties, CAMEL_VERSION, new 
DefaultCamelCatalog().getCatalogVersion());
         writeSetting(main, profileProperties, SPRING_BOOT_VERSION, 
request.springBootVersion);
@@ -568,7 +568,7 @@ public class RunPipeline {
             writeSetting(main, profileProperties, "camel.management.port",
                     () -> String.valueOf(request.managementPort));
         }
-        writeSetting(main, profileProperties, JFR, request.jfrEnabled() ? 
"jfr" : null);
+        writeOption(main, profileProperties, "jfr", JFR, request.jfrEnabled() 
? "jfr" : null);
         writeSetting(main, profileProperties, JFR_PROFILE,
                 request.jfrProfile != null ? request.jfrProfile : null);
         if (request.jfrEnabled()) {
@@ -576,7 +576,7 @@ public class RunPipeline {
             writeSetting(main, profileProperties, 
"camel.main.startupRecorderRuntimeEnabled", "true");
         }
 
-        writeSetting(main, profileProperties, KAMELETS_VERSION, 
request.kameletsVersion);
+        writeOption(main, profileProperties, "kamelets-version", 
KAMELETS_VERSION, request.kameletsVersion);
 
         StringJoiner js = new StringJoiner(",");
         StringJoiner sjReload = new StringJoiner(",");
@@ -968,8 +968,24 @@ public class RunPipeline {
         settings.write(main, existing, key, value);
     }
 
+    /**
+     * Writes the setting of a camel run option: the option given on the 
command line wins over the profile properties,
+     * which are the default when it is not given (CAMEL-26930: before, the 
file won, so with camel.main.tracing=false
+     * in it --trace printed nothing).
+     */
+    void writeOption(KameletMain main, Properties existing, String option, 
String key, String value) {
+        if (request.given(option) && value != null) {
+            // KameletMain reads the camel.jbang settings from the initial 
properties, and camel-main loads the
+            // application properties on top of them: so both, as the file 
would win over the initial property alone
+            main.addInitialProperty(key, value);
+            settings.write(main, existing, key, () -> value);
+        } else {
+            settings.write(main, existing, key, value);
+        }
+    }
+
     private boolean isMcpEnabled(Properties profileProperties) {
-        String val = profileProperties != null
+        String val = profileProperties != null && !request.given("mcp")
                 ? profileProperties.getProperty(MCP, request.mcp ? "true" : 
"false")
                 : (request.mcp ? "true" : "false");
         return "true".equals(val);
diff --git 
a/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/RunProfileProperties.java
 
b/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/RunProfileProperties.java
index 972687bee9b9..8ca91446a342 100644
--- 
a/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/RunProfileProperties.java
+++ 
b/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/RunProfileProperties.java
@@ -165,28 +165,39 @@ public final class RunProfileProperties {
     }
 
     /**
-     * Configures the request with what the properties of a file set, as camel 
run does with its options.
+     * Configures the request with what the properties of a file set, as camel 
run does with its options. An option
+     * given on the command line wins over the file (CAMEL-26930).
      */
     public static void applyTo(RunRequest request, Properties properties) {
         request.mavenResolver = MavenResolver.of(properties, 
request.mavenResolver);
-        request.mavenSettings = properties.getProperty(MAVEN_SETTINGS, 
request.mavenSettings);
-        request.mavenSettingsSecurity = 
properties.getProperty(MAVEN_SETTINGS_SECURITY, request.mavenSettingsSecurity);
-        request.mavenCentralEnabled = "true"
-                .equals(properties.getProperty(MAVEN_CENTRAL_ENABLED, 
request.mavenCentralEnabled ? "true" : "false"));
-        request.mavenApacheSnapshotEnabled = 
"true".equals(properties.getProperty(MAVEN_APACHE_SNAPSHOTS,
-                request.mavenApacheSnapshotEnabled ? "true" : "false"));
-        request.openapi = properties.getProperty(OPEN_API, request.openapi);
-        request.packageScanJars
-                = "true".equals(properties.getProperty(PACKAGE_SCAN_JARS, 
request.packageScanJars ? "true" : "false"));
-        request.camelVersion = properties.getProperty(CAMEL_VERSION, 
request.camelVersion);
-        request.kameletsVersion = properties.getProperty(KAMELETS_VERSION, 
request.kameletsVersion);
+        request.mavenSettings = value(request, "maven-settings", properties, 
MAVEN_SETTINGS, request.mavenSettings);
+        request.mavenSettingsSecurity = value(request, 
"maven-settings-security", properties, MAVEN_SETTINGS_SECURITY,
+                request.mavenSettingsSecurity);
+        request.mavenCentralEnabled = "true".equals(value(request, 
"maven-central-enabled", properties,
+                MAVEN_CENTRAL_ENABLED, request.mavenCentralEnabled ? "true" : 
"false"));
+        request.mavenApacheSnapshotEnabled = "true".equals(value(request, 
"maven-apache-snapshot-enabled", properties,
+                MAVEN_APACHE_SNAPSHOTS, request.mavenApacheSnapshotEnabled ? 
"true" : "false"));
+        request.openapi = value(request, "open-api", properties, OPEN_API, 
request.openapi);
+        request.packageScanJars = "true".equals(value(request, 
"package-scan-jars", properties, PACKAGE_SCAN_JARS,
+                request.packageScanJars ? "true" : "false"));
+        request.camelVersion = value(request, "camel-version", properties, 
CAMEL_VERSION, request.camelVersion);
+        request.kameletsVersion = value(request, "kamelets-version", 
properties, KAMELETS_VERSION, request.kameletsVersion);
         request.springBootVersion = 
properties.getProperty(SPRING_BOOT_VERSION, request.springBootVersion);
-        request.javaVersion = properties.getProperty(JAVA_VERSION, 
request.javaVersion);
+        request.javaVersion = value(request, "java-version", properties, 
JAVA_VERSION, request.javaVersion);
         request.quarkusPlatform = QuarkusPlatform.of(properties,
                 request.quarkusPlatform != null ? request.quarkusPlatform : 
new QuarkusPlatform());
-        request.gav = properties.getProperty(GAV, request.gav);
-        request.stub = properties.getProperty(STUB, request.stub);
-        request.dataDir = properties.getProperty(DATA_DIR, request.dataDir);
-        request.excludes = 
RuntimeUtil.getCommaSeparatedPropertyAsList(properties, EXCLUDES, 
request.excludes);
+        request.gav = value(request, "gav", properties, GAV, request.gav);
+        request.stub = value(request, "stub", properties, STUB, request.stub);
+        request.dataDir = value(request, "data-dir", properties, DATA_DIR, 
request.dataDir);
+        if (!request.given("exclude")) {
+            request.excludes = 
RuntimeUtil.getCommaSeparatedPropertyAsList(properties, EXCLUDES, 
request.excludes);
+        }
+    }
+
+    /**
+     * The value of the option when it is given on the command line, else the 
value of the file, else the default.
+     */
+    private static String value(RunRequest request, String option, Properties 
properties, String key, String value) {
+        return request.given(option) ? value : properties.getProperty(key, 
value);
     }
 }
diff --git 
a/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/RunRequest.java
 
b/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/RunRequest.java
index a14394b3a1cd..25df6cc7dcc2 100644
--- 
a/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/RunRequest.java
+++ 
b/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/RunRequest.java
@@ -44,6 +44,17 @@ public class RunRequest extends ExportRequest {
      */
     public boolean empty;
 
+    /**
+     * The options given on the command line (their names without {@code --}, 
such as {@code trace}): they win over the
+     * same setting in the application properties, which are the default for 
the options not given (CAMEL-26930).
+     */
+    public Set<String> givenOptions = new HashSet<>();
+
+    /** Whether the option (its name without {@code --}) was given on the 
command line. */
+    public boolean given(String option) {
+        return givenOptions.contains(option);
+    }
+
     /**
      * The properties files to use (comma separated); the pipeline adds the 
ones among the files.
      */
diff --git 
a/dsl/camel-jbang/camel-jbang-run/src/test/java/org/apache/camel/dsl/jbang/run/RunPipelineTest.java
 
b/dsl/camel-jbang/camel-jbang-run/src/test/java/org/apache/camel/dsl/jbang/run/RunPipelineTest.java
index 050217d89d46..4858420d68ea 100644
--- 
a/dsl/camel-jbang/camel-jbang-run/src/test/java/org/apache/camel/dsl/jbang/run/RunPipelineTest.java
+++ 
b/dsl/camel-jbang/camel-jbang-run/src/test/java/org/apache/camel/dsl/jbang/run/RunPipelineTest.java
@@ -39,6 +39,67 @@ class RunPipelineTest {
         return request;
     }
 
+    @Test
+    void anOptionGivenOnTheCommandLineWinsOverTheApplicationProperties() {
+        // with camel.main.tracing=false in the file, --trace printed nothing 
(CAMEL-26930)
+        RunRequest request = request();
+        request.givenOptions.add("trace");
+        request.givenOptions.add("console");
+        KameletMain main = new KameletMain("jbang");
+        Properties profile = new Properties();
+        profile.setProperty("camel.main.tracing", "false");
+        profile.setProperty("camel.jbang.console", "false");
+        RunPipeline pipeline = new RunPipeline(request);
+
+        pipeline.writeOption(main, profile, "trace", "camel.main.tracing", 
"true");
+        pipeline.writeOption(main, profile, "console", "camel.jbang.console", 
"true");
+
+        // camel-main binds the override, KameletMain reads the initial 
property
+        
assertThat(main.getOverrideProperties().getProperty("camel.main.tracing")).isEqualTo("true");
+        
assertThat(main.getInitialProperties().getProperty("camel.main.tracing")).isEqualTo("true");
+        
assertThat(main.getOverrideProperties().getProperty("camel.jbang.console")).isEqualTo("true");
+        
assertThat(main.getInitialProperties().getProperty("camel.jbang.console")).isEqualTo("true");
+    }
+
+    @Test
+    void theApplicationPropertiesAreTheDefaultOfAnOptionNotGiven() {
+        RunRequest request = request();
+        KameletMain main = new KameletMain("jbang");
+        Properties profile = new Properties();
+        profile.setProperty("camel.jbang.health", "true");
+        RunPipeline pipeline = new RunPipeline(request);
+
+        pipeline.writeOption(main, profile, "health", "camel.jbang.health", 
"false");
+        pipeline.writeOption(main, profile, "metrics", "camel.jbang.metrics", 
"false");
+
+        
assertThat(main.getInitialProperties().getProperty("camel.jbang.health")).isEqualTo("true");
+        // no override: none was given
+        assertThat(main.getOverrideProperties()).isNull();
+        // neither given nor in the file: the default of the option, as before
+        
assertThat(main.getInitialProperties().getProperty("camel.jbang.metrics")).isEqualTo("false");
+    }
+
+    @Test
+    void theVersionsGivenOnTheCommandLineWinOverTheApplicationProperties() {
+        RunRequest request = request();
+        request.camelVersion = "4.23.0";
+        request.javaVersion = "25";
+        request.stub = "jms";
+        request.givenOptions.add("camel-version");
+        request.givenOptions.add("stub");
+        Properties profile = new Properties();
+        profile.setProperty("camel.jbang.camel-version", "4.18.0");
+        profile.setProperty("camel.jbang.javaVersion", "21");
+        profile.setProperty("camel.jbang.stub", "kafka");
+
+        RunProfileProperties.applyTo(request, profile);
+
+        assertThat(request.camelVersion).isEqualTo("4.23.0");
+        assertThat(request.stub).isEqualTo("jms");
+        // not given: the file
+        assertThat(request.javaVersion).isEqualTo("21");
+    }
+
     @Test
     void shouldAlignManagementPortWithAppPortForOpenApiUi() {
         RunRequest request = request();

Reply via email to