This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch camel-4.22.x
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/camel-4.22.x by this push:
new 3c8aa73d4642 [backport camel-4.22.x] CAMEL-26606:
camel-platform-http-vertx - fail the start when the HTTP server cannot bind its
port (#29265)
3c8aa73d4642 is described below
commit 3c8aa73d4642b59945956111010f4844a61306e7
Author: Andrea Cosentino <[email protected]>
AuthorDate: Thu Nov 5 20:51:35 2026 +0100
[backport camel-4.22.x] CAMEL-26606: camel-platform-http-vertx - fail the
start when the HTTP server cannot bind its port (#29265)
The result of HttpServer.listen is handled in a Vert.x callback: on a failed
bind it logged a WARN and threw there, so startServer() returned normally
and
the CamelContext started with nothing listening. Keep the failure and throw
it
from startServer() after the latch, with the bind error as the cause.
Manual port of cdf2960a6bb7b85763af9d94f2eda07ae9c8b718 (#29221):
camel-4.22.x still uses
the Vert.x listen(port, host, handler) callback, so the same change is
applied
inside it. The upgrade guide note for 4.22.3 is on main (#29264).
(cherry picked from commit cdf2960a6bb7b85763af9d94f2eda07ae9c8b718)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Signed-off-by: Andrea Cosentino <[email protected]>
---
.../http/vertx/VertxPlatformHttpServer.java | 26 ++++++---
.../VertxPlatformHttpServerPortInUseTest.java | 67 ++++++++++++++++++++++
2 files changed, 84 insertions(+), 9 deletions(-)
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 62650db1781e..22b5516a7a83 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
@@ -19,6 +19,7 @@ package org.apache.camel.component.platform.http.vertx;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
+import java.util.concurrent.atomic.AtomicReference;
import io.vertx.core.Handler;
import io.vertx.core.Vertx;
@@ -29,6 +30,7 @@ import io.vertx.ext.web.Router;
import io.vertx.ext.web.RoutingContext;
import org.apache.camel.CamelContext;
import org.apache.camel.CamelContextAware;
+import org.apache.camel.RuntimeCamelException;
import org.apache.camel.StaticService;
import org.apache.camel.api.management.ManagedAttribute;
import org.apache.camel.api.management.ManagedResource;
@@ -224,22 +226,20 @@ public class VertxPlatformHttpServer extends
ServiceSupport implements CamelCont
executor =
context.getExecutorServiceManager().newSingleThreadExecutor(this,
"platform-http-service");
server = vertx.createHttpServer(options);
+ // the result of listen is handled on a Vert.x thread: an exception
thrown there does not reach this thread,
+ // so keep the failure and throw it from here, or the server (and the
CamelContext) starts with nothing listening
+ AtomicReference<Throwable> failure = new AtomicReference<>();
CompletableFuture.runAsync(
() -> {
CountDownLatch latch = new CountDownLatch(1);
server.requestHandler(router).listen(configuration.getBindPort(),
configuration.getBindHost(), result -> {
try {
if (result.failed()) {
- LOGGER.warn("Failed to start Vert.x HttpServer
on {}:{}, reason: {}",
- configuration.getBindHost(),
- configuration.getBindPort(),
- result.cause().getMessage());
-
- throw new RuntimeException(result.cause());
+ failure.set(result.cause());
+ } else {
+ LOGGER.info("Vert.x HttpServer started on
{}:{}", configuration.getBindHost(),
+ server.actualPort());
}
-
- LOGGER.info("Vert.x HttpServer started on {}:{}",
configuration.getBindHost(),
- server.actualPort());
} finally {
latch.countDown();
}
@@ -253,6 +253,14 @@ public class VertxPlatformHttpServer extends
ServiceSupport implements CamelCont
}
},
executor).toCompletableFuture().join();
+
+ Throwable cause = failure.get();
+ if (cause != null) {
+ throw new RuntimeCamelException(
+ "Failed to start Vert.x HttpServer on " +
configuration.getBindHost() + ":" + configuration.getBindPort()
+ + ", reason: " + cause,
+ cause);
+ }
}
protected void stopServer() {
diff --git
a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpServerPortInUseTest.java
b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpServerPortInUseTest.java
new file mode 100644
index 000000000000..42d28023f2bf
--- /dev/null
+++
b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpServerPortInUseTest.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.platform.http.vertx;
+
+import java.net.BindException;
+import java.net.ServerSocket;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.test.AvailablePortFinder;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class VertxPlatformHttpServerPortInUseTest {
+ @RegisterExtension
+ AvailablePortFinder.Port port = AvailablePortFinder.find();
+
+ @Test
+ void startFailsWhenPortIsInUse() throws Exception {
+ try (ServerSocket portInUse = new ServerSocket(port.getPort());
+ CamelContext context = new DefaultCamelContext()) {
+ VertxPlatformHttpServerConfiguration configuration = new
VertxPlatformHttpServerConfiguration();
+ configuration.setBindPort(port.getPort());
+ VertxPlatformHttpServer server = new
VertxPlatformHttpServer(configuration);
+
+ context.addService(server);
+ context.addRoutes(new RouteBuilder() {
+ @Override
+ public void configure() {
+ from("platform-http:/test")
+ .setBody().constant("Hello World");
+ }
+ });
+
+ RuntimeCamelException e =
assertThrows(RuntimeCamelException.class, context::start);
+ assertInstanceOf(BindException.class, e.getCause());
+ assertTrue(e.getMessage().contains(":" + port.getPort()),
e.getMessage());
+ assertFalse(context.isStarted());
+
+ // the failed start stopped the server, so it holds neither the
HTTP server nor its own Vert.x instance
+ assertNull(server.getServer());
+ assertNull(server.getVertx());
+ }
+ }
+}