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

acosentino 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 21e5dc0cc27b CAMEL-22937 - camel-jbang: using different custom ports 
for both embedded and management server runs into an error (#21216)
21e5dc0cc27b is described below

commit 21e5dc0cc27bc99d9594b098cca3b8c4f4542ee3
Author: Andrea Cosentino <[email protected]>
AuthorDate: Tue Feb 3 09:30:09 2026 +0100

    CAMEL-22937 - camel-jbang: using different custom ports for both embedded 
and management server runs into an error (#21216)
    
    Signed-off-by: Andrea Cosentino <[email protected]>
---
 .../platform/http/main/MainHttpServer.java         |   3 +
 .../platform/http/main/ManagementHttpServer.java   |   3 +
 .../http/vertx/VertxPlatformHttpEngine.java        |  32 +++++
 .../http/vertx/VertxPlatformHttpRouter.java        |  34 ++++++
 .../http/vertx/VertxPlatformHttpServer.java        |   3 +-
 .../VertxPlatformHttpServerConfiguration.java      |  20 ++++
 .../http/vertx/VertxPlatformHttpEngineTest.java    | 129 +++++++++++++++++++++
 7 files changed, 223 insertions(+), 1 deletion(-)

diff --git 
a/components/camel-platform-http-main/src/main/java/org/apache/camel/component/platform/http/main/MainHttpServer.java
 
b/components/camel-platform-http-main/src/main/java/org/apache/camel/component/platform/http/main/MainHttpServer.java
index e18de9650040..125913eae0a9 100644
--- 
a/components/camel-platform-http-main/src/main/java/org/apache/camel/component/platform/http/main/MainHttpServer.java
+++ 
b/components/camel-platform-http-main/src/main/java/org/apache/camel/component/platform/http/main/MainHttpServer.java
@@ -207,6 +207,9 @@ public class MainHttpServer extends ServiceSupport 
implements CamelContextAware,
     protected void doInit() throws Exception {
         ObjectHelper.notNull(camelContext, "CamelContext");
 
+        // Mark this as the main server (not management) so the engine can 
identify it
+        
configuration.setServerType(VertxPlatformHttpRouter.SERVER_TYPE_SERVER);
+
         server = new VertxPlatformHttpServer(configuration);
         // adding server to camel-context which will manage shutdown the 
server, so we should not do this here
         camelContext.addService(server);
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 74f96865ba68..376fd86a3b55 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,6 +391,9 @@ public class ManagementHttpServer extends ServiceSupport 
implements CamelContext
             consumer = camelContext.createConsumerTemplate();
         }
 
+        // Mark this as the management server so the engine can identify it
+        
configuration.setServerType(VertxPlatformHttpRouter.SERVER_TYPE_MANAGEMENT);
+
         VertxPlatformHttpServer mainServer = 
camelContext.hasService(VertxPlatformHttpServer.class);
         if (mainServer != null && mainServer.getConfigurationPort() == 
configuration.getPort()) {
             // reuse main server as we should use same port
diff --git 
a/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpEngine.java
 
b/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpEngine.java
index 3f92369b45a4..ddf819c2008d 100644
--- 
a/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpEngine.java
+++ 
b/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpEngine.java
@@ -19,6 +19,7 @@ package org.apache.camel.component.platform.http.vertx;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 
 import io.vertx.core.Handler;
 import io.vertx.ext.web.RoutingContext;
@@ -115,6 +116,37 @@ public class VertxPlatformHttpEngine extends 
ServiceSupport implements PlatformH
                     port = router.getServer().getServer().actualPort();
                 }
             }
+            // When there are multiple servers (e.g., main server and 
management server),
+            // findSingleByType returns null. In this case, look for available 
routers
+            // registered in the registry and prefer the main server 
(SERVER_TYPE_SERVER)
+            // over the management server (SERVER_TYPE_MANAGEMENT).
+            if (port == 0) {
+                Map<String, VertxPlatformHttpRouter> routers
+                        = 
camelContext.getRegistry().findByTypeWithName(VertxPlatformHttpRouter.class);
+                int fallbackPort = 0;
+                for (VertxPlatformHttpRouter router : routers.values()) {
+                    if (router.getServer() != null && 
router.getServer().getServer() != null) {
+                        int actualPort = 
router.getServer().getServer().actualPort();
+                        if (actualPort > 0) {
+                            // Prefer routers marked as main server type
+                            if (router.isMainServer()) {
+                                port = actualPort;
+                                break;
+                            } else if (fallbackPort == 0 && 
!router.isManagementServer()) {
+                                // Keep first non-management router as fallback
+                                fallbackPort = actualPort;
+                            } else if (fallbackPort == 0) {
+                                // Last resort: use management router if 
nothing else available
+                                fallbackPort = actualPort;
+                            }
+                        }
+                    }
+                }
+                // If no main server router was found, use the fallback
+                if (port == 0 && fallbackPort > 0) {
+                    port = fallbackPort;
+                }
+            }
 
             if (port == 0) {
                 //fallback to default
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 d982628df616..0a5f5840f413 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
@@ -38,18 +38,31 @@ public class VertxPlatformHttpRouter implements Router {
     public static final String PLATFORM_HTTP_ROUTER_NAME_ZERO
             = PlatformHttpConstants.PLATFORM_HTTP_COMPONENT_NAME + "-router-0";
 
+    /**
+     * Server type constants for distinguishing between main server and 
management server routers.
+     */
+    public static final String SERVER_TYPE_SERVER = "server";
+    public static final String SERVER_TYPE_MANAGEMENT = "management";
+
     private final String name;
+    private final String serverType;
     private final VertxPlatformHttpServer server;
     private final Vertx vertx;
     private final Router delegate;
     private AllowForwardHeaders allowForward;
 
     public VertxPlatformHttpRouter(VertxPlatformHttpServer server, Vertx 
vertx, Router delegate, String name) {
+        this(server, vertx, delegate, name, null);
+    }
+
+    public VertxPlatformHttpRouter(VertxPlatformHttpServer server, Vertx 
vertx, Router delegate, String name,
+                                   String serverType) {
         this.server = server;
         this.vertx = vertx;
         this.delegate = delegate;
         this.allowForward = AllowForwardHeaders.NONE;
         this.name = name;
+        this.serverType = serverType;
     }
 
     public Vertx vertx() {
@@ -64,6 +77,27 @@ public class VertxPlatformHttpRouter implements Router {
         return this.name;
     }
 
+    /**
+     * Returns the server type (e.g., "server" or "management"), or null if 
not set.
+     */
+    public String getServerType() {
+        return this.serverType;
+    }
+
+    /**
+     * Returns true if this router is for the main server (not management).
+     */
+    public boolean isMainServer() {
+        return SERVER_TYPE_SERVER.equals(serverType);
+    }
+
+    /**
+     * Returns true if this router is for the management server.
+     */
+    public boolean isManagementServer() {
+        return SERVER_TYPE_MANAGEMENT.equals(serverType);
+    }
+
     @Override
     public Route route() {
         return delegate.route();
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 7ccf7032c557..62650db1781e 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
@@ -205,9 +205,10 @@ public class VertxPlatformHttpServer extends 
ServiceSupport implements CamelCont
         router.route(configuration.getPath() + "*").subRouter(subRouter);
 
         String routerName = 
VertxPlatformHttpRouter.getRouterNameFromPort(configuration.getPort());
+        String serverType = configuration.getServerType();
         context.getRegistry().bind(
                 routerName,
-                new VertxPlatformHttpRouter(this, vertx, subRouter, 
routerName) {
+                new VertxPlatformHttpRouter(this, vertx, subRouter, 
routerName, serverType) {
                     @Override
                     public Handler<RoutingContext> bodyHandler() {
                         return createBodyHandler(getCamelContext(), 
configuration);
diff --git 
a/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpServerConfiguration.java
 
b/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpServerConfiguration.java
index b071e7411966..243ac9115c73 100644
--- 
a/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpServerConfiguration.java
+++ 
b/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpServerConfiguration.java
@@ -48,6 +48,7 @@ public class VertxPlatformHttpServerConfiguration {
     private Cors cors = new Cors();
     private SessionConfig sessionConfig = new SessionConfig();
     private AuthenticationConfig authenticationConfig = new 
AuthenticationConfig();
+    private String serverType;
 
     public int getPort() {
         return getBindPort();
@@ -145,6 +146,25 @@ public class VertxPlatformHttpServerConfiguration {
         this.authenticationConfig = authenticationConfig;
     }
 
+    /**
+     * The server type (e.g., "server" or "management") used to distinguish 
between main server and management server.
+     * This is used by {@link VertxPlatformHttpRouter} to help identify the 
correct router when multiple servers are
+     * running.
+     */
+    public String getServerType() {
+        return serverType;
+    }
+
+    /**
+     * Sets the server type (e.g., "server" or "management").
+     *
+     * @see VertxPlatformHttpRouter#SERVER_TYPE_SERVER
+     * @see VertxPlatformHttpRouter#SERVER_TYPE_MANAGEMENT
+     */
+    public void setServerType(String serverType) {
+        this.serverType = serverType;
+    }
+
     public static class SessionConfig {
         private boolean enabled;
         private SessionStoreType storeType = SessionStoreType.LOCAL;
diff --git 
a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpEngineTest.java
 
b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpEngineTest.java
index 6cf069d9df7b..249d624e5796 100644
--- 
a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpEngineTest.java
+++ 
b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpEngineTest.java
@@ -1223,6 +1223,135 @@ public class VertxPlatformHttpEngineTest {
         }
     }
 
+    @Test
+    public void testMultipleServersScenario() throws Exception {
+        // This test simulates CAMEL-22937: when both main server and 
management server are running,
+        // findSingleByType returns null because there are multiple instances 
of VertxPlatformHttpServer.
+        // The engine should prefer the main server (SERVER_TYPE_SERVER) over 
the management server.
+        int mainPort = AvailablePortFinder.getNextAvailable();
+        int managementPort = AvailablePortFinder.getNextAvailable();
+
+        VertxPlatformHttpServerConfiguration mainConf = new 
VertxPlatformHttpServerConfiguration();
+        mainConf.setBindPort(mainPort);
+        mainConf.setServerType(VertxPlatformHttpRouter.SERVER_TYPE_SERVER);
+
+        VertxPlatformHttpServerConfiguration managementConf = new 
VertxPlatformHttpServerConfiguration();
+        managementConf.setBindPort(managementPort);
+        
managementConf.setServerType(VertxPlatformHttpRouter.SERVER_TYPE_MANAGEMENT);
+
+        RestAssured.port = mainPort;
+
+        CamelContext context = new DefaultCamelContext();
+        // Add management server FIRST to verify that the engine still picks 
the main server
+        context.addService(new VertxPlatformHttpServer(managementConf));
+        context.addService(new VertxPlatformHttpServer(mainConf));
+
+        try {
+            context.addRoutes(new RouteBuilder() {
+                @Override
+                public void configure() {
+                    from("platform-http:/test")
+                            .routeId("test")
+                            .setBody().constant("test-response");
+                }
+            });
+
+            context.start();
+
+            // Verify the engine prefers the main server port
+            PlatformHttpEngine engine = 
context.getRegistry().findSingleByType(PlatformHttpEngine.class);
+            assertNotNull(engine);
+            int serverPort = engine.getServerPort();
+            // The port should be the main server port, not the management port
+            assertEquals(mainPort, serverPort);
+
+            // Verify the route works on the main server port
+            given()
+                    .port(serverPort)
+                    .when()
+                    .get("/test")
+                    .then()
+                    .statusCode(200)
+                    .body(equalTo("test-response"));
+
+        } finally {
+            context.stop();
+        }
+    }
+
+    @Test
+    public void testMultipleServersWithCustomPorts() throws Exception {
+        // This test simulates the exact scenario from CAMEL-22937 with custom 
ports like:
+        // camel.server.port = 8084
+        // camel.management.port = 8083
+        // The engine should always prefer the main server port.
+        int serverPort = 8084;
+        int managementPort = 8083;
+
+        // Check if ports are available, otherwise use dynamic ports
+        if (!isPortAvailable(serverPort)) {
+            serverPort = AvailablePortFinder.getNextAvailable();
+        }
+        if (!isPortAvailable(managementPort)) {
+            managementPort = AvailablePortFinder.getNextAvailable();
+        }
+
+        VertxPlatformHttpServerConfiguration mainConf = new 
VertxPlatformHttpServerConfiguration();
+        mainConf.setBindPort(serverPort);
+        mainConf.setServerType(VertxPlatformHttpRouter.SERVER_TYPE_SERVER);
+
+        VertxPlatformHttpServerConfiguration managementConf = new 
VertxPlatformHttpServerConfiguration();
+        managementConf.setBindPort(managementPort);
+        
managementConf.setServerType(VertxPlatformHttpRouter.SERVER_TYPE_MANAGEMENT);
+
+        RestAssured.port = serverPort;
+
+        CamelContext context = new DefaultCamelContext();
+        // Add both servers - the order shouldn't matter since we use server 
type to distinguish
+        context.addService(new VertxPlatformHttpServer(managementConf));
+        context.addService(new VertxPlatformHttpServer(mainConf));
+
+        final int expectedPort = serverPort;
+        try {
+            context.addRoutes(new RouteBuilder() {
+                @Override
+                public void configure() {
+                    from("platform-http:/api/test")
+                            .routeId("api-test")
+                            .setBody().constant("api-response");
+                }
+            });
+
+            context.start();
+
+            // Verify the engine picks the main server port
+            PlatformHttpEngine engine = 
context.getRegistry().findSingleByType(PlatformHttpEngine.class);
+            assertNotNull(engine);
+            assertEquals(expectedPort, engine.getServerPort());
+
+            // Verify the API route works on the main server port
+            given()
+                    .port(expectedPort)
+                    .when()
+                    .get("/api/test")
+                    .then()
+                    .statusCode(200)
+                    .body(equalTo("api-response"));
+
+        } finally {
+            context.stop();
+        }
+    }
+
+    private boolean isPortAvailable(int port) {
+        try (java.net.ServerSocket socket = new java.net.ServerSocket(port)) {
+            socket.setReuseAddress(true);
+            return true;
+        } catch (java.io.IOException e) {
+            return false;
+        }
+    }
+
     static CamelContext createCamelContext() throws Exception {
         return createCamelContext(null);
     }

Reply via email to