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

Reply via email to