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()