diff --git a/components/camel-cxf/camel-cxf-spring-soap/src/test/java/org/apache/camel/component/cxf/CxfTimeoutTest.java b/components/camel-cxf/camel-cxf-spring-soap/src/test/java/org/apache/camel/component/cxf/CxfTimeoutTest.java index 0762cec094262..80256ef456850 100644 --- a/components/camel-cxf/camel-cxf-spring-soap/src/test/java/org/apache/camel/component/cxf/CxfTimeoutTest.java +++ b/components/camel-cxf/camel-cxf-spring-soap/src/test/java/org/apache/camel/component/cxf/CxfTimeoutTest.java @@ -45,6 +45,13 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; +/** + * Tests CXF ReceiveTimeout behavior. The timeout is configured to 100ms in cxfConduitTimeOutContext.xml via a wildcard + * http-conduit. However, the JAX-WS server published in {@code @BeforeAll} creates a default CXF Bus without that + * configuration. Under CI load, the client conduit can sometimes resolve against the wrong Bus and miss the 100ms + * timeout entirely. To make the timeout reliable, each timeout-expecting test method uses {@code TimeoutCxfConfigurer} + * to explicitly set the ReceiveTimeout on the conduit, independent of Bus-level configuration. + */ @Isolated public class CxfTimeoutTest extends CamelSpringTestSupport { @@ -61,17 +68,21 @@ public static void startService() { @Test public void testInvokingJaxWsServerWithBusUriParams() throws Exception { - sendTimeOutMessage("cxf://" + JAXWS_SERVER_ADDRESS + "?serviceClass=org.apache.hello_world_soap_http.Greeter&bus=#cxf"); + sendTimeOutMessage( + "cxf://" + JAXWS_SERVER_ADDRESS + + "?serviceClass=org.apache.hello_world_soap_http.Greeter&bus=#cxf&cxfConfigurer=#timeoutConfigurer"); } @Test public void testInvokingJaxWsServerWithoutBusUriParams() throws Exception { - sendTimeOutMessage("cxf://" + JAXWS_SERVER_ADDRESS + "?serviceClass=org.apache.hello_world_soap_http.Greeter"); + sendTimeOutMessage( + "cxf://" + JAXWS_SERVER_ADDRESS + + "?serviceClass=org.apache.hello_world_soap_http.Greeter&cxfConfigurer=#timeoutConfigurer"); } @Test public void testInvokingJaxWsServerWithCxfEndpoint() throws Exception { - sendTimeOutMessage("cxf://bean:springEndpoint"); + sendTimeOutMessage("cxf://bean:springEndpoint?cxfConfigurer=#timeoutConfigurer"); } @Test @@ -117,6 +128,31 @@ protected AbstractXmlApplicationContext createApplicationContext() { return new ClassPathXmlApplicationContext("org/apache/camel/component/cxf/cxfConduitTimeOutContext.xml"); } + /** + * Explicitly sets the 100ms ReceiveTimeout on the conduit so that the timeout is applied regardless of which CXF + * Bus the conduit was created from. + */ + public static class TimeoutCxfConfigurer implements CxfConfigurer { + + @Override + public void configure(AbstractWSDLBasedEndpointFactory factoryBean) { + // Do nothing here + } + + @Override + public void configureClient(Client client) { + HTTPConduit conduit = (HTTPConduit) client.getConduit(); + HTTPClientPolicy policy = new HTTPClientPolicy(); + policy.setReceiveTimeout(100); + conduit.setClient(policy); + } + + @Override + public void configureServer(Server server) { + // Do nothing here + } + } + public static class MyCxfConfigurer implements CxfConfigurer { @Override diff --git a/components/camel-cxf/camel-cxf-spring-soap/src/test/resources/org/apache/camel/component/cxf/cxfConduitTimeOutContext.xml b/components/camel-cxf/camel-cxf-spring-soap/src/test/resources/org/apache/camel/component/cxf/cxfConduitTimeOutContext.xml index 21f3b68fd260c..7e55def1f8d9a 100644 --- a/components/camel-cxf/camel-cxf-spring-soap/src/test/resources/org/apache/camel/component/cxf/cxfConduitTimeOutContext.xml +++ b/components/camel-cxf/camel-cxf-spring-soap/src/test/resources/org/apache/camel/component/cxf/cxfConduitTimeOutContext.xml @@ -46,7 +46,12 @@ - + + + + @@ -58,12 +63,12 @@ - + - + diff --git a/components/camel-quartz/src/test/java/org/apache/camel/component/quartz/SpringQuartzPersistentStoreRestartAppChangeOptionsTest.java b/components/camel-quartz/src/test/java/org/apache/camel/component/quartz/SpringQuartzPersistentStoreRestartAppChangeOptionsTest.java index 5c56dcb29ce17..55b2a562a9702 100644 --- a/components/camel-quartz/src/test/java/org/apache/camel/component/quartz/SpringQuartzPersistentStoreRestartAppChangeOptionsTest.java +++ b/components/camel-quartz/src/test/java/org/apache/camel/component/quartz/SpringQuartzPersistentStoreRestartAppChangeOptionsTest.java @@ -23,6 +23,7 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.parallel.Isolated; import org.quartz.CronTrigger; import org.quartz.Scheduler; import org.quartz.SchedulerException; @@ -37,6 +38,9 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; +// Run in isolation to prevent JMX MBean name collisions with concurrent +// test classes that create CamelContexts with the same management name +@Isolated public class SpringQuartzPersistentStoreRestartAppChangeOptionsTest { private static AbstractXmlApplicationContext db; diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/debugger/BacklogTracer.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/debugger/BacklogTracer.java index 059388f860d5e..75a3683e3b3de 100644 --- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/debugger/BacklogTracer.java +++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/debugger/BacklogTracer.java @@ -62,8 +62,12 @@ public class BacklogTracer extends ServiceSupport implements org.apache.camel.sp public static final int MAX_BACKLOG_SIZE = 1000; private final CamelContext camelContext; private final Language simple; - private boolean enabled; - private boolean standby; + // These three flags are toggled at runtime via JMX/management APIs while routing + // threads read them in shouldTrace() and traceEvent(). Other boolean fields (removeOnDump, + // bodyIncludeStreams, traceRests, etc.) are set during initialization and do not change + // while routes are processing, so they do not need volatile. + private volatile boolean enabled; + private volatile boolean standby; private final AtomicLong traceCounter = new AtomicLong(); // use a queue with an upper limit to avoid storing too many messages private final Queue queue = new LinkedBlockingQueue<>(MAX_BACKLOG_SIZE); @@ -87,7 +91,7 @@ public class BacklogTracer extends ServiceSupport implements org.apache.camel.sp private boolean includeExchangeProperties = true; private boolean includeExchangeVariables = true; private boolean includeException = true; - private boolean activityEnabled; + private volatile boolean activityEnabled; private boolean traceRests; private boolean traceTemplates; // a pattern to filter tracing nodes