From 4a6071faf7c2e04814c5dc35f5ed615f4353ea97 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Wed, 6 May 2026 07:26:33 +0200 Subject: [PATCH 1/2] CAMEL-22527: Fix flaky HttpRouteTest and JettyFailoverRoundRobinTest Co-Authored-By: Claude Opus 4.6 (1M context) --- .../component/jetty/JettyHttpComponent.java | 8 ++-- .../jetty/JettyFailoverRoundRobinTest.java | 39 +++++++++---------- 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/JettyHttpComponent.java b/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/JettyHttpComponent.java index 5e03d9b8cf775..a82c5217795e2 100644 --- a/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/JettyHttpComponent.java +++ b/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/JettyHttpComponent.java @@ -412,13 +412,15 @@ private void enableJmx(Server server) { } } - private void enableSessionSupport(Server server, String connectorKey) { + private void enableSessionSupport(Server server, String connectorKey) throws Exception { ServletContextHandler context = server.getDescendant(ServletContextHandler.class); if (context.getSessionHandler() == null) { SessionHandler sessionHandler = new SessionHandler(); if (context.isStarted()) { - throw new IllegalStateException( - "Server has already been started. Cannot enabled sessionSupport on " + connectorKey); + LOG.debug("Restarting Jetty server to enable session support on {}", connectorKey); + server.stop(); + context.setSessionHandler(sessionHandler); + server.start(); } else { context.setSessionHandler(sessionHandler); } diff --git a/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/JettyFailoverRoundRobinTest.java b/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/JettyFailoverRoundRobinTest.java index 5259ff901d449..af56a2ce2b2f1 100644 --- a/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/JettyFailoverRoundRobinTest.java +++ b/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/JettyFailoverRoundRobinTest.java @@ -16,15 +16,18 @@ */ package org.apache.camel.component.jetty; +import java.util.HashSet; +import java.util.Set; + import org.apache.camel.Exchange; import org.apache.camel.builder.RouteBuilder; -import org.apache.camel.component.mock.MockEndpoint; import org.apache.camel.test.AvailablePortFinder; import org.apache.camel.test.junit6.CamelTestSupport; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; public class JettyFailoverRoundRobinTest extends CamelTestSupport { @@ -39,27 +42,23 @@ public class JettyFailoverRoundRobinTest extends CamelTestSupport { @Test void testJettyFailoverRoundRobin() throws Exception { - getMockEndpoint("mock:bad").expectedMessageCount(1); - getMockEndpoint("mock:bad2").expectedMessageCount(1); - getMockEndpoint("mock:good").expectedMessageCount(1); - getMockEndpoint("mock:good2").expectedMessageCount(0); - - String reply = template.requestBody("direct:start", null, String.class); - assertEquals("Good", reply); - - MockEndpoint.assertIsSatisfied(context); - - // reset mocks and send a message again to see that round robin - // continue where it should - MockEndpoint.resetMocks(context); + // Send two requests through the failover round-robin load balancer. + // The round-robin starting index is not guaranteed, so we verify + // that both good endpoints are reached across the two requests + // (one each), confirming both failover and round-robin behavior. + String reply1 = template.requestBody("direct:start", null, String.class); + assertTrue("Good".equals(reply1) || "Also good".equals(reply1), + "Expected 'Good' or 'Also good' but was: " + reply1); - getMockEndpoint("mock:bad").expectedMessageCount(0); - getMockEndpoint("mock:bad2").expectedMessageCount(0); - getMockEndpoint("mock:good").expectedMessageCount(0); - getMockEndpoint("mock:good2").expectedMessageCount(1); + String reply2 = template.requestBody("direct:start", null, String.class); + assertTrue("Good".equals(reply2) || "Also good".equals(reply2), + "Expected 'Good' or 'Also good' but was: " + reply2); - reply = template.requestBody("direct:start", null, String.class); - assertEquals("Also good", reply); + Set replies = new HashSet<>(); + replies.add(reply1); + replies.add(reply2); + assertEquals(2, replies.size(), + "Round robin should hit both good endpoints, but got: " + reply1 + " and " + reply2); } @Override From 290f3254c3d53dd962b2987596690c2733304ac6 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Wed, 6 May 2026 08:26:51 +0200 Subject: [PATCH 2/2] CAMEL-22527: Update JettySessionSupportTest for new restart behavior Co-Authored-By: Claude Opus 4.6 (1M context) --- .../jetty/JettySessionSupportTest.java | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/JettySessionSupportTest.java b/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/JettySessionSupportTest.java index c07176de97331..12f68257e309e 100644 --- a/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/JettySessionSupportTest.java +++ b/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/JettySessionSupportTest.java @@ -21,7 +21,6 @@ import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; class JettySessionSupportTest extends BaseJettyTest { @@ -31,22 +30,24 @@ void setup() { } @Test - void testJettySessionSupportInvalid() { - RouteBuilder routeBuilder = new RouteBuilder() { + void testJettySessionSupportOnExistingServer() throws Exception { + context.addRoutes(new RouteBuilder() { @Override public void configure() { - from("jetty:http://localhost:{{port}}/hello").to("mock:foo"); + from("jetty:http://localhost:{{port}}/hello").transform(simple("Hello ${body}")); - from("jetty:http://localhost:{{port}}/bye?sessionSupport=true").to("mock:bar"); + from("jetty:http://localhost:{{port}}/bye?sessionSupport=true").transform(simple("Bye ${body}")); } - }; + }); + context.start(); - assertThrows( - IllegalStateException.class, - () -> context.addRoutes(routeBuilder), - "Server has already been started. Cannot enabled sessionSupport on http:localhost:%d".formatted(getPort())); + try { + String reply = template.requestBody("http://localhost:{{port}}/hello", "World", String.class); + assertEquals("Hello World", reply); - if (context.isStarted()) { + reply = template.requestBody("http://localhost:{{port}}/bye", "World", String.class); + assertEquals("Bye World", reply); + } finally { context.stop(); } }