You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2025/12/01 09:52:37 UTC

(camel) 01/01: CAMEL-22736: camel-jbang - port=0 will dynamic assign free port making it easier to run multiple instances on the same host.

This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch zero
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 637658e3f1830bbf23f72a28c4021dbb46533698
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Dec 1 10:52:16 2025 +0100

    CAMEL-22736: camel-jbang - port=0 will dynamic assign free port making it easier to run multiple instances on the same host.
---
 .../main/camel-main-configuration-metadata.json      |  4 ++--
 .../platform/http/main/ManagementHttpServer.java     |  4 ++--
 .../http/vertx/VertxPlatformHttpConsumer.java        |  8 ++++++++
 .../platform/http/vertx/VertxPlatformHttpRouter.java | 16 ++++++++++------
 .../platform/http/vertx/VertxPlatformHttpServer.java |  9 +++++++--
 .../META-INF/camel-main-configuration-metadata.json  |  4 ++--
 core/camel-main/src/main/docs/main.adoc              |  4 ++--
 .../HttpManagementServerConfigurationProperties.java |  4 ++--
 .../main/HttpServerConfigurationProperties.java      |  4 ++--
 .../apache/camel/dsl/jbang/core/commands/Run.java    | 20 ++++++++++++++------
 10 files changed, 51 insertions(+), 26 deletions(-)

diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json
index 07521281b375..4ea76d9c5bdc 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json
@@ -213,7 +213,7 @@
     { "name": "camel.management.jwtKeystoreType", "required": false, "description": "Type of the keystore used for JWT tokens validation (jks, pkcs12, etc.).", "sourceType": "org.apache.camel.main.HttpManagementServerConfigurationProperties", "type": "string", "javaType": "java.lang.String", "secret": false },
     { "name": "camel.management.metricsEnabled", "required": false, "description": "Whether to enable metrics. If enabled then you can access metrics on context-path: \/observe\/metrics", "sourceType": "org.apache.camel.main.HttpManagementServerConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": false, "secret": false },
     { "name": "camel.management.path", "required": false, "description": "Context-path to use for embedded HTTP server", "sourceType": "org.apache.camel.main.HttpManagementServerConfigurationProperties", "type": "string", "javaType": "java.lang.String", "defaultValue": "\/", "secret": false },
-    { "name": "camel.management.port", "required": false, "description": "Port to use for binding embedded HTTP server", "sourceType": "org.apache.camel.main.HttpManagementServerConfigurationProperties", "type": "integer", "javaType": "int", "defaultValue": 8080, "secret": false },
+    { "name": "camel.management.port", "required": false, "description": "Port to use for binding embedded HTTP management server. Use 0 to dynamic assign a free random port number.", "sourceType": "org.apache.camel.main.HttpManagementServerConfigurationProperties", "type": "integer", "javaType": "int", "defaultValue": 8080, "secret": false },
     { "name": "camel.management.sendEnabled", "required": false, "description": "Whether to enable sending messages to Camel via HTTP. This makes it possible to use Camel to send messages to Camel endpoint URIs via HTTP.", "sourceType": "org.apache.camel.main.HttpManagementServerConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": false, "secret": false },
     { "name": "camel.management.uploadEnabled", "required": false, "description": "Whether to enable file upload via HTTP (not intended for production use). This functionality is for development to be able to reload Camel routes and code with source changes (if reload is enabled). If enabled then you can upload\/delete files via HTTP PUT\/DELETE on context-path: \/q\/upload\/{name}. You must also configure the uploadSourceDir option.", "sourceType": "org.apache.camel.main.HttpManagementS [...]
     { "name": "camel.management.uploadSourceDir", "required": false, "description": "Source directory when upload is enabled.", "sourceType": "org.apache.camel.main.HttpManagementServerConfigurationProperties", "type": "string", "javaType": "java.lang.String", "secret": false },
@@ -322,7 +322,7 @@
     { "name": "camel.server.jwtKeystoreType", "required": false, "description": "Type of the keystore used for JWT tokens validation (jks, pkcs12, etc.).", "sourceType": "org.apache.camel.main.HttpServerConfigurationProperties", "type": "string", "javaType": "java.lang.String", "secret": false },
     { "name": "camel.server.maxBodySize", "required": false, "description": "Maximum HTTP body size the embedded HTTP server can accept.", "sourceType": "org.apache.camel.main.HttpServerConfigurationProperties", "type": "integer", "javaType": "java.lang.Long", "secret": false },
     { "name": "camel.server.path", "required": false, "description": "Context-path to use for embedded HTTP server", "sourceType": "org.apache.camel.main.HttpServerConfigurationProperties", "type": "string", "javaType": "java.lang.String", "defaultValue": "\/", "secret": false },
-    { "name": "camel.server.port", "required": false, "description": "Port to use for binding embedded HTTP server", "sourceType": "org.apache.camel.main.HttpServerConfigurationProperties", "type": "integer", "javaType": "int", "defaultValue": 8080, "secret": false },
+    { "name": "camel.server.port", "required": false, "description": "Port to use for binding embedded HTTP server. Use 0 to dynamic assign a free random port number.", "sourceType": "org.apache.camel.main.HttpServerConfigurationProperties", "type": "integer", "javaType": "int", "defaultValue": 8080, "secret": false },
     { "name": "camel.server.staticContextPath", "required": false, "description": "The context-path to use for serving static content. By default, the root path is used. And if there is an index.html page then this is automatically loaded.", "sourceType": "org.apache.camel.main.HttpServerConfigurationProperties", "type": "string", "javaType": "java.lang.String", "defaultValue": "\/", "secret": false },
     { "name": "camel.server.staticEnabled", "required": false, "description": "Whether serving static files is enabled. If enabled then Camel can host html\/js and other web files that makes it possible to include small web applications.", "sourceType": "org.apache.camel.main.HttpServerConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": false, "secret": false },
     { "name": "camel.server.staticSourceDir", "required": false, "description": "Additional directory that holds static content when static is enabled.", "sourceType": "org.apache.camel.main.HttpServerConfigurationProperties", "type": "string", "javaType": "java.lang.String", "secret": false },
diff --git a/components/camel-platform-http-main/src/main/java/org/apache/camel/component/platform/http/main/ManagementHttpServer.java b/components/camel-platform-http-main/src/main/java/org/apache/camel/component/platform/http/main/ManagementHttpServer.java
index 523078705f9c..6be0825328f7 100644
--- a/components/camel-platform-http-main/src/main/java/org/apache/camel/component/platform/http/main/ManagementHttpServer.java
+++ b/components/camel-platform-http-main/src/main/java/org/apache/camel/component/platform/http/main/ManagementHttpServer.java
@@ -391,8 +391,8 @@ public class ManagementHttpServer extends ServiceSupport implements CamelContext
         }
 
         VertxPlatformHttpServer mainServer = camelContext.hasService(VertxPlatformHttpServer.class);
-        if (mainServer != null && mainServer.getPort() == configuration.getPort()) {
-            // reuse main server as we use same port
+        if (mainServer != null && mainServer.getConfigurationPort() == configuration.getPort()) {
+            // reuse main server as we should use same port
             server = mainServer;
         } else {
             server = new VertxPlatformHttpServer(configuration);
diff --git a/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpConsumer.java b/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpConsumer.java
index 2c7b19ca6ba9..119289eb3de7 100644
--- a/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpConsumer.java
+++ b/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpConsumer.java
@@ -60,6 +60,7 @@ import org.apache.camel.util.MimeTypeHelper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import static org.apache.camel.component.platform.http.vertx.VertxPlatformHttpRouter.PLATFORM_HTTP_ROUTER_NAME_ZERO;
 import static org.apache.camel.component.platform.http.vertx.VertxPlatformHttpSupport.isFormUrlEncoded;
 import static org.apache.camel.component.platform.http.vertx.VertxPlatformHttpSupport.isMultiPartFormData;
 import static org.apache.camel.component.platform.http.vertx.VertxPlatformHttpSupport.populateCamelHeaders;
@@ -112,6 +113,13 @@ public class VertxPlatformHttpConsumer extends DefaultConsumer
         methods = Method.parseList(getEndpoint().getHttpMethodRestrict());
         path = configureEndpointPath(getEndpoint());
         router = VertxPlatformHttpRouter.lookup(getEndpoint().getCamelContext(), routerName);
+        if (router == null) {
+            // dynamic assigned port number, then lookup using -0
+            router = VertxPlatformHttpRouter.lookup(getEndpoint().getCamelContext(), PLATFORM_HTTP_ROUTER_NAME_ZERO);
+        }
+        if (router == null) {
+            throw new IllegalArgumentException("No PlatformHttpEngine created and setup in registry with name: " + routerName);
+        }
         if (!getEndpoint().isHttpProxy() && getEndpoint().isUseStreaming()) {
             httpRequestBodyHandler = new StreamingHttpRequestBodyHandler(router.bodyHandler());
         } else if (!getEndpoint().isHttpProxy() && !getEndpoint().isUseBodyHandler()) {
diff --git a/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpRouter.java b/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpRouter.java
index b9fbc6280711..d982628df616 100644
--- a/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpRouter.java
+++ b/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpRouter.java
@@ -33,7 +33,10 @@ import org.apache.camel.component.platform.http.PlatformHttpConstants;
 import org.apache.camel.support.CamelContextHelper;
 
 public class VertxPlatformHttpRouter implements Router {
+
     public static final String PLATFORM_HTTP_ROUTER_NAME = PlatformHttpConstants.PLATFORM_HTTP_COMPONENT_NAME + "-router";
+    public static final String PLATFORM_HTTP_ROUTER_NAME_ZERO
+            = PlatformHttpConstants.PLATFORM_HTTP_COMPONENT_NAME + "-router-0";
 
     private final String name;
     private final VertxPlatformHttpServer server;
@@ -292,21 +295,22 @@ public class VertxPlatformHttpRouter implements Router {
     //
     // **********************
 
+    /**
+     * Default router lookup method.
+     */
     public static VertxPlatformHttpRouter lookup(CamelContext camelContext, String routerName) {
-        return CamelContextHelper.mandatoryLookup(
+        return CamelContextHelper.lookup(
                 camelContext,
                 routerName,
                 VertxPlatformHttpRouter.class);
     }
 
-    @Deprecated
     /**
-     * Default router lookup method. Used for backward compatibility only. You should instead use @lookup(CamelContext,
-     * String)
+     * Default router lookup method. Used for backward compatibility only.
      *
-     * @param  camelContext
-     * @return              the default port router
+     * @see #lookup(CamelContext, String)
      */
+    @Deprecated
     public static VertxPlatformHttpRouter lookup(CamelContext camelContext) {
         return lookup(camelContext, getRouterNameFromPort(VertxPlatformHttpServerConfiguration.DEFAULT_BIND_PORT));
     }
diff --git a/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpServer.java b/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpServer.java
index 1c289d6a6cb2..7ccf7032c557 100644
--- a/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpServer.java
+++ b/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpServer.java
@@ -122,7 +122,7 @@ public class VertxPlatformHttpServer extends ServiceSupport implements CamelCont
         }
     }
 
-    @ManagedAttribute(description = "HTTP port number")
+    @ManagedAttribute(description = "HTTP port number (actual)")
     public int getPort() {
         if (server != null) {
             return server.actualPort();
@@ -130,6 +130,11 @@ public class VertxPlatformHttpServer extends ServiceSupport implements CamelCont
         return configuration.getBindPort();
     }
 
+    @ManagedAttribute(description = "HTTP port number (configured)")
+    public int getConfigurationPort() {
+        return configuration.getBindPort();
+    }
+
     @ManagedAttribute(description = "HTTP hostname")
     public String getHost() {
         return configuration.getBindHost();
@@ -233,7 +238,7 @@ public class VertxPlatformHttpServer extends ServiceSupport implements CamelCont
                             }
 
                             LOGGER.info("Vert.x HttpServer started on {}:{}", configuration.getBindHost(),
-                                    configuration.getBindPort());
+                                    server.actualPort());
                         } finally {
                             latch.countDown();
                         }
diff --git a/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json b/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json
index 07521281b375..4ea76d9c5bdc 100644
--- a/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json
+++ b/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json
@@ -213,7 +213,7 @@
     { "name": "camel.management.jwtKeystoreType", "required": false, "description": "Type of the keystore used for JWT tokens validation (jks, pkcs12, etc.).", "sourceType": "org.apache.camel.main.HttpManagementServerConfigurationProperties", "type": "string", "javaType": "java.lang.String", "secret": false },
     { "name": "camel.management.metricsEnabled", "required": false, "description": "Whether to enable metrics. If enabled then you can access metrics on context-path: \/observe\/metrics", "sourceType": "org.apache.camel.main.HttpManagementServerConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": false, "secret": false },
     { "name": "camel.management.path", "required": false, "description": "Context-path to use for embedded HTTP server", "sourceType": "org.apache.camel.main.HttpManagementServerConfigurationProperties", "type": "string", "javaType": "java.lang.String", "defaultValue": "\/", "secret": false },
-    { "name": "camel.management.port", "required": false, "description": "Port to use for binding embedded HTTP server", "sourceType": "org.apache.camel.main.HttpManagementServerConfigurationProperties", "type": "integer", "javaType": "int", "defaultValue": 8080, "secret": false },
+    { "name": "camel.management.port", "required": false, "description": "Port to use for binding embedded HTTP management server. Use 0 to dynamic assign a free random port number.", "sourceType": "org.apache.camel.main.HttpManagementServerConfigurationProperties", "type": "integer", "javaType": "int", "defaultValue": 8080, "secret": false },
     { "name": "camel.management.sendEnabled", "required": false, "description": "Whether to enable sending messages to Camel via HTTP. This makes it possible to use Camel to send messages to Camel endpoint URIs via HTTP.", "sourceType": "org.apache.camel.main.HttpManagementServerConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": false, "secret": false },
     { "name": "camel.management.uploadEnabled", "required": false, "description": "Whether to enable file upload via HTTP (not intended for production use). This functionality is for development to be able to reload Camel routes and code with source changes (if reload is enabled). If enabled then you can upload\/delete files via HTTP PUT\/DELETE on context-path: \/q\/upload\/{name}. You must also configure the uploadSourceDir option.", "sourceType": "org.apache.camel.main.HttpManagementS [...]
     { "name": "camel.management.uploadSourceDir", "required": false, "description": "Source directory when upload is enabled.", "sourceType": "org.apache.camel.main.HttpManagementServerConfigurationProperties", "type": "string", "javaType": "java.lang.String", "secret": false },
@@ -322,7 +322,7 @@
     { "name": "camel.server.jwtKeystoreType", "required": false, "description": "Type of the keystore used for JWT tokens validation (jks, pkcs12, etc.).", "sourceType": "org.apache.camel.main.HttpServerConfigurationProperties", "type": "string", "javaType": "java.lang.String", "secret": false },
     { "name": "camel.server.maxBodySize", "required": false, "description": "Maximum HTTP body size the embedded HTTP server can accept.", "sourceType": "org.apache.camel.main.HttpServerConfigurationProperties", "type": "integer", "javaType": "java.lang.Long", "secret": false },
     { "name": "camel.server.path", "required": false, "description": "Context-path to use for embedded HTTP server", "sourceType": "org.apache.camel.main.HttpServerConfigurationProperties", "type": "string", "javaType": "java.lang.String", "defaultValue": "\/", "secret": false },
-    { "name": "camel.server.port", "required": false, "description": "Port to use for binding embedded HTTP server", "sourceType": "org.apache.camel.main.HttpServerConfigurationProperties", "type": "integer", "javaType": "int", "defaultValue": 8080, "secret": false },
+    { "name": "camel.server.port", "required": false, "description": "Port to use for binding embedded HTTP server. Use 0 to dynamic assign a free random port number.", "sourceType": "org.apache.camel.main.HttpServerConfigurationProperties", "type": "integer", "javaType": "int", "defaultValue": 8080, "secret": false },
     { "name": "camel.server.staticContextPath", "required": false, "description": "The context-path to use for serving static content. By default, the root path is used. And if there is an index.html page then this is automatically loaded.", "sourceType": "org.apache.camel.main.HttpServerConfigurationProperties", "type": "string", "javaType": "java.lang.String", "defaultValue": "\/", "secret": false },
     { "name": "camel.server.staticEnabled", "required": false, "description": "Whether serving static files is enabled. If enabled then Camel can host html\/js and other web files that makes it possible to include small web applications.", "sourceType": "org.apache.camel.main.HttpServerConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": false, "secret": false },
     { "name": "camel.server.staticSourceDir", "required": false, "description": "Additional directory that holds static content when static is enabled.", "sourceType": "org.apache.camel.main.HttpServerConfigurationProperties", "type": "string", "javaType": "java.lang.String", "secret": false },
diff --git a/core/camel-main/src/main/docs/main.adoc b/core/camel-main/src/main/docs/main.adoc
index cceb9356acb8..132a1189431e 100644
--- a/core/camel-main/src/main/docs/main.adoc
+++ b/core/camel-main/src/main/docs/main.adoc
@@ -208,7 +208,7 @@ The camel.server supports 18 options, which are listed below.
 | *camel.server.jwtKeystoreType* | Type of the keystore used for JWT tokens validation (jks, pkcs12, etc.). |  | String
 | *camel.server.maxBodySize* | Maximum HTTP body size the embedded HTTP server can accept. |  | Long
 | *camel.server.path* | Context-path to use for embedded HTTP server | / | String
-| *camel.server.port* | Port to use for binding embedded HTTP server | 8080 | int
+| *camel.server.port* | Port to use for binding embedded HTTP server. Use 0 to dynamic assign a free random port number. | 8080 | int
 | *camel.server.staticContextPath* | The context-path to use for serving static content. By default, the root path is used. And if there is an index.html page then this is automatically loaded. | / | String
 | *camel.server.staticEnabled* | Whether serving static files is enabled. If enabled then Camel can host html/js and other web files that makes it possible to include small web applications. | false | boolean
 | *camel.server.staticSourceDir* | Additional directory that holds static content when static is enabled. |  | String
@@ -241,7 +241,7 @@ The camel.management supports 24 options, which are listed below.
 | *camel.management.jwtKeystore{zwsp}Type* | Type of the keystore used for JWT tokens validation (jks, pkcs12, etc.). |  | String
 | *camel.management.metrics{zwsp}Enabled* | Whether to enable metrics. If enabled then you can access metrics on context-path: /observe/metrics | false | boolean
 | *camel.management.path* | Context-path to use for embedded HTTP server | / | String
-| *camel.management.port* | Port to use for binding embedded HTTP server | 8080 | int
+| *camel.management.port* | Port to use for binding embedded HTTP management server. Use 0 to dynamic assign a free random port number. | 8080 | int
 | *camel.management.sendEnabled* | Whether to enable sending messages to Camel via HTTP. This makes it possible to use Camel to send messages to Camel endpoint URIs via HTTP. | false | boolean
 | *camel.management.uploadEnabled* | Whether to enable file upload via HTTP (not intended for production use). This functionality is for development to be able to reload Camel routes and code with source changes (if reload is enabled). If enabled then you can upload/delete files via HTTP PUT/DELETE on context-path: /q/upload/\{name}. You must also configure the uploadSourceDir option. | false | boolean
 | *camel.management.uploadSource{zwsp}Dir* | Source directory when upload is enabled. |  | String
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/HttpManagementServerConfigurationProperties.java b/core/camel-main/src/main/java/org/apache/camel/main/HttpManagementServerConfigurationProperties.java
index 3208e3c13de2..7d4031b60201 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/HttpManagementServerConfigurationProperties.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/HttpManagementServerConfigurationProperties.java
@@ -110,7 +110,7 @@ public class HttpManagementServerConfigurationProperties implements BootstrapClo
     }
 
     /**
-     * Port to use for binding embedded HTTP server
+     * Port to use for binding embedded HTTP management server. Use 0 to dynamic assign a free random port number.
      */
     public void setPort(int port) {
         this.port = port;
@@ -375,7 +375,7 @@ public class HttpManagementServerConfigurationProperties implements BootstrapClo
     }
 
     /**
-     * Port to use for binding embedded HTTP management server
+     * Port to use for binding embedded HTTP management server. Use 0 to dynamic assign a free random port number.
      */
     public HttpManagementServerConfigurationProperties withPort(int port) {
         this.port = port;
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/HttpServerConfigurationProperties.java b/core/camel-main/src/main/java/org/apache/camel/main/HttpServerConfigurationProperties.java
index 1ee4e23d2f09..d90975ab0c3c 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/HttpServerConfigurationProperties.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/HttpServerConfigurationProperties.java
@@ -105,7 +105,7 @@ public class HttpServerConfigurationProperties implements BootstrapCloseable {
     }
 
     /**
-     * Port to use for binding embedded HTTP server
+     * Port to use for binding embedded HTTP server. Use 0 to dynamic assign a free random port number.
      */
     public void setPort(int port) {
         this.port = port;
@@ -300,7 +300,7 @@ public class HttpServerConfigurationProperties implements BootstrapCloseable {
     }
 
     /**
-     * Port to use for binding embedded HTTP server
+     * Port to use for binding embedded HTTP server. Use 0 to dynamic assign a free random port number.
      */
     public HttpServerConfigurationProperties withPort(int port) {
         this.port = port;
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 f1c803051c15..e71a5f3d4a83 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
@@ -296,10 +296,13 @@ public class Run extends CamelCommand {
             description = "Local directory (or github link) for loading Kamelets (takes precedence). Multiple directories can be specified separated by comma.")
     String localKameletDir;
 
-    @Option(names = { "--port" }, description = "Embeds a local HTTP server on this port", defaultValue = "8080")
-    int port;
+    @Option(names = { "--port" },
+            description = "Embeds a local HTTP server on this port (use 0 to dynamic assign a free random port number)",
+            defaultValue = "8080")
+    int port = -1;
 
-    @Option(names = { "--management-port" }, description = "To use a dedicated port for HTTP management")
+    @Option(names = { "--management-port" },
+            description = "To use a dedicated port for HTTP management (use 0 to dynamic assign a free random port number)")
     int managementPort = -1;
 
     @Option(names = { "--console" }, defaultValue = "false",
@@ -712,9 +715,14 @@ public class Run extends CamelCommand {
                 () -> maxSeconds > 0 ? String.valueOf(maxSeconds) : null);
         writeSetting(main, profileProperties, "camel.main.durationMaxIdleSeconds",
                 () -> maxIdleSeconds > 0 ? String.valueOf(maxIdleSeconds) : null);
-        writeSetting(main, profileProperties, "camel.server.port",
-                () -> port > 0 && port != 8080 ? String.valueOf(port) : null);
-        if (managementPort != -1) {
+        if (port != -1 && port != 8080) {
+            writeSetting(main, profileProperties, "camel.server.port", () -> String.valueOf(port));
+        }
+        if (port == 0 && managementPort == -1) {
+            // use same port for management
+            managementPort = 0;
+        }
+        if (managementPort != -1 && managementPort != 8080) {
             writeSetting(main, profileProperties, "camel.management.port", () -> String.valueOf(managementPort));
         }
         writeSetting(main, profileProperties, JFR, jfr || jfrProfile != null ? "jfr" : null);