This is an automated email from the ASF dual-hosted git repository.

apupier 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 1fbdddc37d21 CAMEL-25158: Fix flaky RouteIdTransactedIT by using one 
queue per test
1fbdddc37d21 is described below

commit 1fbdddc37d21b29c83dc5e2e335d3c84dc366629
Author: AurĂ©lien Pupier <[email protected]>
AuthorDate: Tue Oct 13 11:55:22 2026 +0200

    CAMEL-25158: Fix flaky RouteIdTransactedIT by using one queue per test
    
    testRouteIdFailed intermittently failed with:
      mock://result Received message count. Expected: <0> but was: <1>
    
    Root cause: both tests used the same queue on the singleton Artemis
    broker, which outlives the CamelContext of each test. testRouteId
    asserts on mock:result from inside the JMS transaction, i.e. possibly
    before the session commit has completed. When the context is torn down
    first, the commit loses the race, the message is rolled back and stays
    on the queue. testRouteIdFailed then starts a new context whose
    consumer receives the redelivered "Hello World", which reaches
    mock:result and breaks expectedMessageCount(0).
    
    How it was found:
    - 20 sequential runs, plus 12 runs under CPU load, all passed, so the
      race could not be hit with normal timing.
    - Mock expectations are set per test (and tests run in order), so a
      stale mock state was ruled out: the message had to be a real one.
    - Simulating a slow commit (JmsTransactionManager.doCommit sleeping
      1.5s) reproduced the exact failure on the first run.
    - Dumping mock:result's exchanges on failure showed
      body=Hello World, JMSRedelivered=true, JMSXDeliveryCount=2, i.e. the
      message of the previous test.
    
    Fix: use a distinct queue per test method so a message left over by one
    test can no longer be consumed by the next one. With the slow-commit
    simulation the fixed test passed 5/5 runs.
    
    Co-authored-by: IBM Bob 2.2.1
    Signed-off-by: AurĂ©lien Pupier <[email protected]>
---
 .../jms/integration/spring/tx/RouteIdTransactedIT.java    | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git 
a/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/spring/tx/RouteIdTransactedIT.java
 
b/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/spring/tx/RouteIdTransactedIT.java
index 7cb94960ab5d..8676a2a07bf5 100644
--- 
a/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/spring/tx/RouteIdTransactedIT.java
+++ 
b/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/spring/tx/RouteIdTransactedIT.java
@@ -27,6 +27,7 @@ import org.junit.jupiter.api.Order;
 import org.junit.jupiter.api.Tag;
 import org.junit.jupiter.api.Tags;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInfo;
 import org.junit.jupiter.api.TestMethodOrder;
 import org.springframework.context.support.ClassPathXmlApplicationContext;
 
@@ -36,6 +37,14 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 @TestMethodOrder(MethodOrderer.OrderAnnotation.class)
 public class RouteIdTransactedIT extends AbstractSpringJMSITSupport {
 
+    // each test uses its own queue: the broker is shared and outlives the 
CamelContext, so a message rolled back at
+    // the end of one test would otherwise be redelivered to the consumer of 
the next one
+    private final String queueName;
+
+    RouteIdTransactedIT(TestInfo testInfo) {
+        queueName = "RouteIdTransactedIT." + 
testInfo.getTestMethod().orElseThrow().getName();
+    }
+
     @Override
     protected ClassPathXmlApplicationContext createApplicationContext() {
         return new ClassPathXmlApplicationContext(
@@ -51,7 +60,7 @@ public class RouteIdTransactedIT extends 
AbstractSpringJMSITSupport {
         getMockEndpoint("mock:error").expectedMessageCount(0);
         getMockEndpoint("mock:result").expectedMessageCount(1);
 
-        template.sendBody("activemq:queue:RouteIdTransactedIT", "Hello World");
+        template.sendBody("activemq:queue:" + queueName, "Hello World");
 
         MockEndpoint.assertIsSatisfied(context, 30, TimeUnit.SECONDS);
 
@@ -68,7 +77,7 @@ public class RouteIdTransactedIT extends 
AbstractSpringJMSITSupport {
         getMockEndpoint("mock:error").expectedMessageCount(1);
         getMockEndpoint("mock:result").expectedMessageCount(0);
 
-        template.sendBody("activemq:queue:RouteIdTransactedIT", "Kaboom");
+        template.sendBody("activemq:queue:" + queueName, "Kaboom");
 
         MockEndpoint.assertIsSatisfied(context, 30, TimeUnit.SECONDS);
 
@@ -81,7 +90,7 @@ public class RouteIdTransactedIT extends 
AbstractSpringJMSITSupport {
         return new RouteBuilder() {
             @Override
             public void configure() {
-                
from("activemq:queue:RouteIdTransactedIT?transacted=true").id("myCoolRoute")
+                from("activemq:queue:" + queueName + 
"?transacted=true").id("myCoolRoute")
                         
.onException(IllegalArgumentException.class).handled(true).to("log:bar").to("mock:error").end()
                         .transacted()
                         .choice()

Reply via email to