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);
}