This is an automated email from the ASF dual-hosted git repository.
gnodet 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 4a5e970c28f9 CAMEL-21917: Fix flaky JMS transacted and security tests
(#21917)
4a5e970c28f9 is described below
commit 4a5e970c28f913d3ba1e11c742a1e21b138bab56
Author: Guillaume Nodet <[email protected]>
AuthorDate: Thu Mar 12 07:53:39 2026 +0100
CAMEL-21917: Fix flaky JMS transacted and security tests (#21917)
- Pre-create custom DLQ queues in Artemis broker config, since Artemis
does not auto-create dead letter queues for custom DLQ addresses
without autoCreateDeadLetterResources enabled
- Use per-class DLQ names to avoid interference between concurrent tests
- Set explicit maxDeliveryAttempts (1 or 3) per test for faster and
deterministic redelivery behavior
- Enforce test method ordering with @TestMethodOrder/@Order to prevent
message leakage via shared broker queues (RouteIdTransactedIT,
JmsToJmsTransactedIT)
- Increase Awaitility/timeout values for CI stability under load
- Fix JmsToJmsTransactedSecurityIT to work on JDK 25 by using
SASL_PLAINTEXT for Artemis security configuration
Co-authored-by: Claude Opus 4.6 <[email protected]>
---
.../jms/JmsProducerWithJMSHeaderTest.java | 2 +-
.../jms/JmsRouteWithInOnlyAndMultipleAcksTest.java | 2 +-
.../component/jms/JmsRouteWithInOnlyTest.java | 2 +-
.../jms/async/AsyncConsumerInOutTwoTest.java | 2 +-
.../JmsAddAndRemoveRouteManagementIT.java | 36 ++++++++--
.../JmsDestinationProducedHeaderIT.java | 4 +-
.../jms/integration/JmsLoadBalanceFailOverIT.java | 2 +-
...eFailOverWithForceSendOriginalJmsMessageIT.java | 2 +-
.../jms/integration/JmsRoutingSlipInOutIT.java | 2 +-
.../jms/integration/JmsToDSendDynamicIT.java | 6 +-
.../issues/JmsAnotherCustomJMSReplyToIT.java | 2 +-
.../polling/JmsPollingHighTimeOutIT.java | 2 +-
.../spring/polling/JmsPollingConsumerSpringIT.java | 2 +-
.../spring/tx/JmsToJmsTransactedIT.java | 27 +++++--
.../integration/spring/tx/RouteIdTransactedIT.java | 6 ++
.../JMSTransactionIsTransactedRedeliveredIT.java | 2 +-
.../tx/security/JmsToJmsTransactedSecurityIT.java | 17 ++++-
...dLetterChannelHandlerRollbackOnExceptionIT.java | 32 ++++++---
...tterChannelNotHandlerRollbackOnExceptionIT.java | 83 +++++++++++++++++++---
...TransactedOnExceptionRollbackOnExceptionIT.java | 28 ++++++--
.../camel/component/jms/support/MyCoolBean.java | 4 +-
.../services/AbstractArtemisEmbeddedService.java | 12 ++--
22 files changed, 214 insertions(+), 63 deletions(-)
diff --git
a/components/camel-jms/src/test/java/org/apache/camel/component/jms/JmsProducerWithJMSHeaderTest.java
b/components/camel-jms/src/test/java/org/apache/camel/component/jms/JmsProducerWithJMSHeaderTest.java
index 254029bb6a5b..0d872aa4e6f4 100644
---
a/components/camel-jms/src/test/java/org/apache/camel/component/jms/JmsProducerWithJMSHeaderTest.java
+++
b/components/camel-jms/src/test/java/org/apache/camel/component/jms/JmsProducerWithJMSHeaderTest.java
@@ -203,7 +203,7 @@ public class JmsProducerWithJMSHeaderTest extends
AbstractJMSTest {
assertNotNull(bar, "Should be a message on queue");
template.send("activemq:queue:fooJmsProducerWithJMSHeaderTest?preserveMessageQos=true",
bar);
- Awaitility.await().atMost(1, TimeUnit.SECONDS)
+ Awaitility.await().atMost(5, TimeUnit.SECONDS)
.untilAsserted(() -> MockEndpoint.assertIsSatisfied(context));
}
diff --git
a/components/camel-jms/src/test/java/org/apache/camel/component/jms/JmsRouteWithInOnlyAndMultipleAcksTest.java
b/components/camel-jms/src/test/java/org/apache/camel/component/jms/JmsRouteWithInOnlyAndMultipleAcksTest.java
index 17bd37feb858..7379dd92c7fb 100644
---
a/components/camel-jms/src/test/java/org/apache/camel/component/jms/JmsRouteWithInOnlyAndMultipleAcksTest.java
+++
b/components/camel-jms/src/test/java/org/apache/camel/component/jms/JmsRouteWithInOnlyAndMultipleAcksTest.java
@@ -36,7 +36,7 @@ import org.junit.jupiter.api.extension.RegisterExtension;
import static org.junit.jupiter.api.Assertions.assertEquals;
-@Timeout(10)
+@Timeout(30)
@TestInstance(TestInstance.Lifecycle.PER_METHOD)
public class JmsRouteWithInOnlyAndMultipleAcksTest extends AbstractJMSTest {
diff --git
a/components/camel-jms/src/test/java/org/apache/camel/component/jms/JmsRouteWithInOnlyTest.java
b/components/camel-jms/src/test/java/org/apache/camel/component/jms/JmsRouteWithInOnlyTest.java
index dbcdb93ee772..d8df6a7fc2b9 100644
---
a/components/camel-jms/src/test/java/org/apache/camel/component/jms/JmsRouteWithInOnlyTest.java
+++
b/components/camel-jms/src/test/java/org/apache/camel/component/jms/JmsRouteWithInOnlyTest.java
@@ -40,7 +40,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
* Unit test inspired by user forum
*/
@TestInstance(TestInstance.Lifecycle.PER_METHOD)
-@Timeout(10)
+@Timeout(30)
public class JmsRouteWithInOnlyTest extends AbstractJMSTest {
@Order(2)
diff --git
a/components/camel-jms/src/test/java/org/apache/camel/component/jms/async/AsyncConsumerInOutTwoTest.java
b/components/camel-jms/src/test/java/org/apache/camel/component/jms/async/AsyncConsumerInOutTwoTest.java
index 70aade6e3f0c..2709425f029b 100644
---
a/components/camel-jms/src/test/java/org/apache/camel/component/jms/async/AsyncConsumerInOutTwoTest.java
+++
b/components/camel-jms/src/test/java/org/apache/camel/component/jms/async/AsyncConsumerInOutTwoTest.java
@@ -32,7 +32,7 @@ import org.junit.jupiter.api.extension.RegisterExtension;
import static org.junit.jupiter.api.Assertions.assertEquals;
-@Timeout(10)
+@Timeout(30)
public class AsyncConsumerInOutTwoTest extends AbstractJMSTest {
@Order(2)
diff --git
a/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/JmsAddAndRemoveRouteManagementIT.java
b/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/JmsAddAndRemoveRouteManagementIT.java
index 59c57374e83a..42b91af22429 100644
---
a/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/JmsAddAndRemoveRouteManagementIT.java
+++
b/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/JmsAddAndRemoveRouteManagementIT.java
@@ -16,7 +16,10 @@
*/
package org.apache.camel.component.jms.integration;
+import java.util.HashSet;
import java.util.Set;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
import javax.management.MBeanServer;
import javax.management.ObjectName;
@@ -31,6 +34,8 @@ import org.apache.camel.impl.DefaultCamelContext;
import org.apache.camel.test.infra.core.CamelContextExtension;
import org.apache.camel.test.infra.core.DefaultCamelContextExtension;
import org.apache.camel.test.infra.core.annotations.ContextFixture;
+import org.awaitility.Awaitility;
+import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Tag;
@@ -39,8 +44,6 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Timeout;
import org.junit.jupiter.api.extension.RegisterExtension;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
/**
* Test that all thread pools are removed when adding and removing a route
dynamically. This test manipulates the thread
* pools, so it's not a good candidate for running in parallel.
@@ -68,8 +71,9 @@ public class JmsAddAndRemoveRouteManagementIT extends
AbstractJMSTest {
@Test
public void testAddAndRemoveRoute() throws Exception {
MBeanServer mbeanServer = getMBeanServer();
+ ObjectName query = new ObjectName("*:type=threadpools,*");
- Set<ObjectName> before = mbeanServer.queryNames(new
ObjectName("*:type=threadpools,*"), null);
+ Set<ObjectName> before = mbeanServer.queryNames(query, null);
getMockEndpoint("mock:result").expectedMessageCount(1);
@@ -81,8 +85,20 @@ public class JmsAddAndRemoveRouteManagementIT extends
AbstractJMSTest {
}
});
- Set<ObjectName> during = mbeanServer.queryNames(new
ObjectName("*:type=threadpools,*"), null);
- assertEquals(before.size() + 1, during.size(), "There should be one
more thread pool in JMX");
+ // Wait for the new route's thread pool to be registered and identify
it
+ AtomicReference<Set<ObjectName>> duringRef = new AtomicReference<>();
+ Awaitility.await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> {
+ Set<ObjectName> during = mbeanServer.queryNames(query, null);
+ Set<ObjectName> added = new HashSet<>(during);
+ added.removeAll(before);
+ Assertions.assertFalse(added.isEmpty(),
+ "There should be at least one new thread pool in JMX");
+ duringRef.set(during);
+ });
+
+ // Identify the thread pools added by the new route
+ Set<ObjectName> addedPools = new HashSet<>(duringRef.get());
+ addedPools.removeAll(before);
template.sendBody("activemq:queue:JmsAddAndRemoveRouteManagementTest.in",
"Hello World");
@@ -92,8 +108,14 @@ public class JmsAddAndRemoveRouteManagementIT extends
AbstractJMSTest {
context.getRouteController().stopRoute("myNewRoute");
context.removeRoute("myNewRoute");
- Set<ObjectName> after = mbeanServer.queryNames(new
ObjectName("*:type=threadpools,*"), null);
- assertEquals(before.size(), after.size(), "Should have removed all
thread pools from removed route");
+ // Verify the thread pools from the removed route are cleaned up
+ Awaitility.await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> {
+ Set<ObjectName> after = mbeanServer.queryNames(query, null);
+ for (ObjectName added : addedPools) {
+ Assertions.assertFalse(after.contains(added),
+ "Thread pool from removed route should be cleaned up:
" + added);
+ }
+ });
}
@Override
diff --git
a/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/JmsDestinationProducedHeaderIT.java
b/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/JmsDestinationProducedHeaderIT.java
index a304b4d98639..9ad99a66cf9d 100644
---
a/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/JmsDestinationProducedHeaderIT.java
+++
b/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/JmsDestinationProducedHeaderIT.java
@@ -50,9 +50,9 @@ public class JmsDestinationProducedHeaderIT extends
AbstractPersistentJMSTest {
assertEquals(2, count, "There should only be 1 activemq endpoint");
// and the messages should be in the queues
- String out =
consumer.receiveBody("activemq:queue:JmsDestinationProducedHeaderTest.bar2",
2000, String.class);
+ String out =
consumer.receiveBody("activemq:queue:JmsDestinationProducedHeaderTest.bar2",
5000, String.class);
assertEquals("Hello bar", out);
- out =
consumer.receiveBody("activemq:queue:JmsDestinationProducedHeaderTest.beer2",
2000, String.class);
+ out =
consumer.receiveBody("activemq:queue:JmsDestinationProducedHeaderTest.beer2",
5000, String.class);
assertEquals("Hello beer", out);
}
diff --git
a/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/JmsLoadBalanceFailOverIT.java
b/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/JmsLoadBalanceFailOverIT.java
index 306f5f60d3bf..20f3b2b872b6 100644
---
a/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/JmsLoadBalanceFailOverIT.java
+++
b/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/JmsLoadBalanceFailOverIT.java
@@ -36,7 +36,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* Unit test for Camel loadbalancer failover with JMS
*/
-@Timeout(10)
+@Timeout(30)
public class JmsLoadBalanceFailOverIT extends CamelTestSupport {
@RegisterExtension
diff --git
a/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/JmsLoadBalanceFailOverWithForceSendOriginalJmsMessageIT.java
b/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/JmsLoadBalanceFailOverWithForceSendOriginalJmsMessageIT.java
index cd49a3fd0372..e8ec14f16e4a 100644
---
a/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/JmsLoadBalanceFailOverWithForceSendOriginalJmsMessageIT.java
+++
b/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/JmsLoadBalanceFailOverWithForceSendOriginalJmsMessageIT.java
@@ -38,7 +38,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* Unit test for Camel loadbalancer failover with JMS
*/
-@Timeout(10)
+@Timeout(30)
public class JmsLoadBalanceFailOverWithForceSendOriginalJmsMessageIT extends
AbstractJMSTest {
@Order(2)
@RegisterExtension
diff --git
a/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/JmsRoutingSlipInOutIT.java
b/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/JmsRoutingSlipInOutIT.java
index 58a9a4d1838f..323639a5e84c 100644
---
a/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/JmsRoutingSlipInOutIT.java
+++
b/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/JmsRoutingSlipInOutIT.java
@@ -36,7 +36,7 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Timeout;
import org.junit.jupiter.api.extension.RegisterExtension;
-@Timeout(10)
+@Timeout(30)
public class JmsRoutingSlipInOutIT extends AbstractJMSTest {
@Order(2)
diff --git
a/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/JmsToDSendDynamicIT.java
b/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/JmsToDSendDynamicIT.java
index 09fc1e72d248..71f6b178b5b2 100644
---
a/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/JmsToDSendDynamicIT.java
+++
b/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/JmsToDSendDynamicIT.java
@@ -34,16 +34,16 @@ public class JmsToDSendDynamicIT extends
AbstractPersistentJMSTest {
assertEquals(1, count, "There should only be 1 activemq endpoint");
// and the messages should be in the queues
- String out =
consumer.receiveBody("activemq:queue:JmsToDSendDynamicIT.bar", 2000,
String.class);
+ String out =
consumer.receiveBody("activemq:queue:JmsToDSendDynamicIT.bar", 5000,
String.class);
assertEquals("Hello bar", out);
- out = consumer.receiveBody("activemq:queue:JmsToDSendDynamicIT.beer",
2000, String.class);
+ out = consumer.receiveBody("activemq:queue:JmsToDSendDynamicIT.beer",
5000, String.class);
assertEquals("Hello beer", out);
}
@Test
public void testToDSlashed() {
template.sendBodyAndHeader("direct:startSlashed", "Hello bar",
"where", "JmsToDSendDynamicIT.bar");
- String out =
consumer.receiveBody("activemq://JmsToDSendDynamicIT.bar", 2000, String.class);
+ String out =
consumer.receiveBody("activemq://JmsToDSendDynamicIT.bar", 5000, String.class);
assertEquals("Hello bar", out);
}
diff --git
a/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/issues/JmsAnotherCustomJMSReplyToIT.java
b/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/issues/JmsAnotherCustomJMSReplyToIT.java
index 234b83a604b4..4689932bc0e5 100644
---
a/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/issues/JmsAnotherCustomJMSReplyToIT.java
+++
b/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/issues/JmsAnotherCustomJMSReplyToIT.java
@@ -69,7 +69,7 @@ public class JmsAnotherCustomJMSReplyToIT extends
AbstractJMSTest {
// send reply
template.sendBody("activemq:" + replyTo.getQueueName(), "My name is
Arnio");
- Awaitility.await().atMost(2, TimeUnit.SECONDS).untilAsserted(() ->
MockEndpoint.assertIsSatisfied(context));
+ Awaitility.await().atMost(5, TimeUnit.SECONDS).untilAsserted(() ->
MockEndpoint.assertIsSatisfied(context));
}
@Override
diff --git
a/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/polling/JmsPollingHighTimeOutIT.java
b/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/polling/JmsPollingHighTimeOutIT.java
index 170320906ef7..948bc092f1bf 100644
---
a/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/polling/JmsPollingHighTimeOutIT.java
+++
b/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/polling/JmsPollingHighTimeOutIT.java
@@ -33,7 +33,7 @@ class JmsPollingHighTimeOutIT extends JmsPollingConsumerIT {
@BeforeEach
void setupConsumer() {
Executors.newSingleThreadExecutor().execute(() -> {
- body =
consumer.receiveBody("activemq:queue.JmsPollingConsumerTest.start", 3000,
String.class);
+ body =
consumer.receiveBody("activemq:queue.JmsPollingConsumerTest.start", 5000,
String.class);
template.sendBody("activemq:queue.JmsPollingConsumerTest.foo",
body + " Claus");
});
}
diff --git
a/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/spring/polling/JmsPollingConsumerSpringIT.java
b/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/spring/polling/JmsPollingConsumerSpringIT.java
index 8e004e3dbc97..276f6961d9fa 100644
---
a/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/spring/polling/JmsPollingConsumerSpringIT.java
+++
b/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/spring/polling/JmsPollingConsumerSpringIT.java
@@ -95,7 +95,7 @@ public class JmsPollingConsumerSpringIT extends
SpringJMSBasic {
StringBuilder result = new StringBuilder();
Exchange exchange;
- while ((exchange =
consumer.receive("jms:JmsPollingConsumerSpringITQueue", 2000)) != null) {
+ while ((exchange =
consumer.receive("jms:JmsPollingConsumerSpringITQueue", 5000)) != null) {
result.append(exchange.getIn().getBody(String.class));
}
diff --git
a/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/spring/tx/JmsToJmsTransactedIT.java
b/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/spring/tx/JmsToJmsTransactedIT.java
index a008a29f0d76..0da4420f14a7 100644
---
a/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/spring/tx/JmsToJmsTransactedIT.java
+++
b/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/spring/tx/JmsToJmsTransactedIT.java
@@ -16,10 +16,12 @@
*/
package org.apache.camel.component.jms.integration.spring.tx;
+import org.apache.activemq.artemis.api.core.QueueConfiguration;
+import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.mock.MockEndpoint;
import org.apache.camel.test.infra.artemis.services.ArtemisService;
-import org.apache.camel.test.infra.artemis.services.ArtemisServiceFactory;
+import org.apache.camel.test.infra.artemis.services.ArtemisVMService;
import org.apache.camel.test.spring.junit6.CamelSpringTestSupport;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
@@ -29,6 +31,7 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.api.extension.RegisterExtension;
+import org.junit.jupiter.api.parallel.Isolated;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -36,11 +39,25 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
@TestInstance(TestInstance.Lifecycle.PER_METHOD)
@Tags({ @Tag("not-parallel"), @Tag("spring"), @Tag("tx") })
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
+@Isolated("Uses a shared DLQ queue name and embedded VM broker")
public final class JmsToJmsTransactedIT extends CamelSpringTestSupport {
+ private static final int MAX_DELIVERY_ATTEMPTS = 3;
+
@Order(0)
@RegisterExtension
- public static ArtemisService service =
ArtemisServiceFactory.createVMService();
+ public static ArtemisService service = createArtemisService();
+
+ static ArtemisService createArtemisService() {
+ ArtemisVMService svc = new ArtemisVMService();
+ svc.customConfiguration(cfg -> {
+ cfg.getAddressSettings().values()
+ .forEach(s ->
s.setMaxDeliveryAttempts(MAX_DELIVERY_ATTEMPTS));
+ cfg.addQueueConfiguration(
+
QueueConfiguration.of("DLQ").setRoutingType(RoutingType.ANYCAST));
+ });
+ return svc;
+ }
/**
* Used by spring xml configurations
@@ -97,7 +114,7 @@ public final class JmsToJmsTransactedIT extends
CamelSpringTestSupport {
bar.expectedMessageCount(0);
MockEndpoint start = getMockEndpoint("mock:start");
- start.expectedMessageCount(7); // default number of redeliveries by
AMQ is 6 so we get 6+1
+ start.expectedMessageCount(MAX_DELIVERY_ATTEMPTS);
template.sendBody("activemq:queue:JmsToJmsTransactedIT", "Hello
World");
@@ -125,14 +142,14 @@ public final class JmsToJmsTransactedIT extends
CamelSpringTestSupport {
bar.expectedMessageCount(0);
MockEndpoint start = getMockEndpoint("mock:start");
- start.expectedMessageCount(7); // default number of redeliveries by
AMQ is 6 so we get 6+1
+ start.expectedMessageCount(MAX_DELIVERY_ATTEMPTS);
template.sendBody("activemq:queue:JmsToJmsTransactedIT", "Hello
World");
MockEndpoint.assertIsSatisfied(context);
// it should be moved to DLQ in JMS broker
- Object body = consumer.receiveBody("activemq:queue:DLQ", 2000);
+ Object body = consumer.receiveBody("activemq:queue:DLQ", 10000);
assertEquals("Hello World", body);
}
}
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 acca1b2dfdb5..114ea0a20e69 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
@@ -19,14 +19,18 @@ package
org.apache.camel.component.jms.integration.spring.tx;
import org.apache.camel.builder.RouteBuilder;
import
org.apache.camel.component.jms.integration.spring.AbstractSpringJMSITSupport;
import org.apache.camel.component.mock.MockEndpoint;
+import org.junit.jupiter.api.MethodOrderer;
+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.TestMethodOrder;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import static org.junit.jupiter.api.Assertions.assertEquals;
@Tags({ @Tag("not-parallel"), @Tag("spring"), @Tag("tx") })
+@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class RouteIdTransactedIT extends AbstractSpringJMSITSupport {
@Override
@@ -35,6 +39,7 @@ public class RouteIdTransactedIT extends
AbstractSpringJMSITSupport {
"/org/apache/camel/component/jms/integration/spring/tx/RouteIdTransactedIT.xml");
}
+ @Order(1)
@Test
public void testRouteId() throws Exception {
getMockEndpoint("mock:error").expectedMessageCount(0);
@@ -48,6 +53,7 @@ public class RouteIdTransactedIT extends
AbstractSpringJMSITSupport {
assertEquals("myCoolRoute", id);
}
+ @Order(2)
@Test
public void testRouteIdFailed() throws Exception {
getMockEndpoint("mock:error").expectedMessageCount(1);
diff --git
a/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/spring/tx/error/JMSTransactionIsTransactedRedeliveredIT.java
b/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/spring/tx/error/JMSTransactionIsTransactedRedeliveredIT.java
index d46ce0be2c81..bf53bf8b2e38 100644
---
a/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/spring/tx/error/JMSTransactionIsTransactedRedeliveredIT.java
+++
b/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/spring/tx/error/JMSTransactionIsTransactedRedeliveredIT.java
@@ -84,7 +84,7 @@ public class JMSTransactionIsTransactedRedeliveredIT extends
AbstractSpringJMSIT
// check JMX stats
// need a little sleep to ensure JMX is updated
- final Set<ObjectName> objectNames = Awaitility.await().atMost(1000,
TimeUnit.MILLISECONDS)
+ final Set<ObjectName> objectNames = Awaitility.await().atMost(5,
TimeUnit.SECONDS)
.until(() -> getMBeanServer()
.queryNames(new
ObjectName("org.apache.camel:context=camel-*,type=routes,name=\"myRoute\""),
null),
Matchers.hasSize(1));
diff --git
a/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/spring/tx/security/JmsToJmsTransactedSecurityIT.java
b/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/spring/tx/security/JmsToJmsTransactedSecurityIT.java
index 014eb9637690..e44c69f081ce 100644
---
a/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/spring/tx/security/JmsToJmsTransactedSecurityIT.java
+++
b/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/spring/tx/security/JmsToJmsTransactedSecurityIT.java
@@ -16,6 +16,9 @@
*/
package org.apache.camel.component.jms.integration.spring.tx.security;
+import org.apache.activemq.artemis.core.config.FileDeploymentManager;
+import org.apache.activemq.artemis.core.config.impl.FileConfiguration;
+import org.apache.activemq.artemis.core.config.impl.LegacyJMSConfiguration;
import org.apache.activemq.artemis.core.config.impl.SecurityConfiguration;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.ActiveMQServers;
@@ -49,9 +52,17 @@ public class JmsToJmsTransactedSecurityIT extends
CamelSpringTestSupport {
ActiveMQJAASSecurityManager securityManager
= new
ActiveMQJAASSecurityManager(InVMLoginModule.class.getName(), securityConfig);
- activeMQServer = ActiveMQServers.newActiveMQServer(
-
"org/apache/camel/component/jms/integration/spring/tx/security/artemis-security.xml",
null,
- securityManager);
+ FileConfiguration config = new FileConfiguration();
+ LegacyJMSConfiguration legacyJMSConfiguration = new
LegacyJMSConfiguration(config);
+ new FileDeploymentManager(
+
"org/apache/camel/component/jms/integration/spring/tx/security/artemis-security.xml")
+
.addDeployable(config).addDeployable(legacyJMSConfiguration).readConfiguration();
+
+ // Use the 4-arg version with enablePersistence=false to honor the
XML's persistence-enabled=false.
+ // The 3-arg version hardcodes enablePersistence=true, which causes
the broker to get stuck
+ // in STARTING state on JDK 25 due to journal initialization issues.
+ // TODO: revert this workaround once
https://github.com/apache/activemq-artemis/pull/6286 is released
+ activeMQServer = ActiveMQServers.newActiveMQServer(config, null,
securityManager, false);
activeMQServer.start();
}
diff --git
a/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/tx/JmsTransactedDeadLetterChannelHandlerRollbackOnExceptionIT.java
b/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/tx/JmsTransactedDeadLetterChannelHandlerRollbackOnExceptionIT.java
index 29470a832c97..ee99afecb2a8 100644
---
a/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/tx/JmsTransactedDeadLetterChannelHandlerRollbackOnExceptionIT.java
+++
b/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/tx/JmsTransactedDeadLetterChannelHandlerRollbackOnExceptionIT.java
@@ -18,6 +18,7 @@ package org.apache.camel.component.jms.integration.tx;
import jakarta.jms.ConnectionFactory;
+import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.camel.CamelContext;
import org.apache.camel.Exchange;
import org.apache.camel.Handler;
@@ -26,7 +27,7 @@ import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.jms.JmsComponent;
import org.apache.camel.test.infra.artemis.common.ConnectionFactoryHelper;
import org.apache.camel.test.infra.artemis.services.ArtemisService;
-import org.apache.camel.test.infra.artemis.services.ArtemisServiceFactory;
+import org.apache.camel.test.infra.artemis.services.ArtemisVMService;
import org.apache.camel.test.junit6.CamelTestSupport;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Tags;
@@ -36,11 +37,25 @@ import org.junit.jupiter.api.extension.RegisterExtension;
import static
org.apache.camel.component.jms.JmsComponent.jmsComponentTransacted;
import static org.junit.jupiter.api.Assertions.assertNull;
-// This test cannot run in parallel: it reads from the default DLQ and there
could be more messages there
@Tags({ @Tag("not-parallel"), @Tag("transaction") })
public class JmsTransactedDeadLetterChannelHandlerRollbackOnExceptionIT
extends CamelTestSupport {
+
+ private static final String DLQ_NAME
+ = "DLQ." +
JmsTransactedDeadLetterChannelHandlerRollbackOnExceptionIT.class.getSimpleName();
+
@RegisterExtension
- public static ArtemisService service =
ArtemisServiceFactory.createVMService();
+ public static ArtemisService service = createArtemisService();
+
+ static ArtemisService createArtemisService() {
+ ArtemisVMService svc = new ArtemisVMService();
+ svc.customConfiguration(
+ cfg -> cfg.getAddressSettings().values()
+ .forEach(s -> {
+ s.setMaxDeliveryAttempts(1);
+ s.setDeadLetterAddress(SimpleString.of(DLQ_NAME));
+ }));
+ return svc;
+ }
public static class BadErrorHandler {
@Handler
@@ -51,10 +66,6 @@ public class
JmsTransactedDeadLetterChannelHandlerRollbackOnExceptionIT extends
protected final String testingEndpoint = "activemq:test." +
getClass().getName();
- protected boolean isHandleNew() {
- return true;
- }
-
@Override
protected RouteBuilder createRouteBuilder() {
return new RouteBuilder() {
@@ -63,7 +74,7 @@ public class
JmsTransactedDeadLetterChannelHandlerRollbackOnExceptionIT extends
// we use DLC to handle the exception but if it throw a new
exception
// then the DLC handles that too (the transaction will always
commit)
errorHandler(deadLetterChannel("bean:" +
BadErrorHandler.class.getName())
- .deadLetterHandleNewException(isHandleNew())
+ .deadLetterHandleNewException(true)
.logNewException(true));
from(testingEndpoint)
@@ -78,8 +89,8 @@ public class
JmsTransactedDeadLetterChannelHandlerRollbackOnExceptionIT extends
template.sendBody(testingEndpoint, "Hello World");
// as we handle new exception, then the exception is ignored
- // and causes the transaction to commit, so there is no message in the
ActiveMQ DLQ queue
- Object dlqBody = consumer.receiveBody("activemq:DLQ", 2000);
+ // and causes the transaction to commit, so there is no message in the
DLQ queue
+ Object dlqBody = consumer.receiveBody("activemq:" + DLQ_NAME, 10000);
assertNull(dlqBody, "Should not rollback the transaction");
}
@@ -87,7 +98,6 @@ public class
JmsTransactedDeadLetterChannelHandlerRollbackOnExceptionIT extends
protected CamelContext createCamelContext() throws Exception {
CamelContext camelContext = super.createCamelContext();
- // no redeliveries
ConnectionFactory connectionFactory =
ConnectionFactoryHelper.createConnectionFactory(service, 0);
JmsComponent component = jmsComponentTransacted(connectionFactory);
diff --git
a/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/tx/JmsTransactedDeadLetterChannelNotHandlerRollbackOnExceptionIT.java
b/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/tx/JmsTransactedDeadLetterChannelNotHandlerRollbackOnExceptionIT.java
index 1ae8f0e8f077..e48d5b895534 100644
---
a/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/tx/JmsTransactedDeadLetterChannelNotHandlerRollbackOnExceptionIT.java
+++
b/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/tx/JmsTransactedDeadLetterChannelNotHandlerRollbackOnExceptionIT.java
@@ -16,31 +16,98 @@
*/
package org.apache.camel.component.jms.integration.tx;
+import jakarta.jms.ConnectionFactory;
+
+import org.apache.activemq.artemis.api.core.QueueConfiguration;
+import org.apache.activemq.artemis.api.core.RoutingType;
+import org.apache.activemq.artemis.api.core.SimpleString;
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.Handler;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.jms.JmsComponent;
+import org.apache.camel.test.infra.artemis.common.ConnectionFactoryHelper;
+import org.apache.camel.test.infra.artemis.services.ArtemisService;
+import org.apache.camel.test.infra.artemis.services.ArtemisVMService;
+import org.apache.camel.test.junit6.CamelTestSupport;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Tags;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import static
org.apache.camel.component.jms.JmsComponent.jmsComponentTransacted;
import static org.junit.jupiter.api.Assertions.assertEquals;
-// This test cannot run in parallel: it reads from the default DLQ and there
could be more messages there
@Tags({ @Tag("not-parallel"), @Tag("transaction") })
-public class JmsTransactedDeadLetterChannelNotHandlerRollbackOnExceptionIT
- extends JmsTransactedDeadLetterChannelHandlerRollbackOnExceptionIT {
+public class JmsTransactedDeadLetterChannelNotHandlerRollbackOnExceptionIT
extends CamelTestSupport {
- @Override
- protected boolean isHandleNew() {
- return false;
+ private static final String DLQ_NAME
+ = "DLQ." +
JmsTransactedDeadLetterChannelNotHandlerRollbackOnExceptionIT.class.getSimpleName();
+
+ @RegisterExtension
+ public static ArtemisService service = createArtemisService();
+
+ static ArtemisService createArtemisService() {
+ ArtemisVMService svc = new ArtemisVMService();
+ svc.customConfiguration(cfg -> {
+ cfg.getAddressSettings().values()
+ .forEach(s -> {
+ s.setMaxDeliveryAttempts(1);
+ s.setDeadLetterAddress(SimpleString.of(DLQ_NAME));
+ });
+ cfg.addQueueConfiguration(
+
QueueConfiguration.of(DLQ_NAME).setRoutingType(RoutingType.ANYCAST));
+ });
+ return svc;
}
+ public static class BadErrorHandler {
+ @Handler
+ public void onException(Exchange exchange, Exception exception) {
+ throw new RuntimeCamelException("error in errorhandler");
+ }
+ }
+
+ private final String testingEndpoint = "activemq:test." +
getClass().getName();
+
@Override
+ protected RouteBuilder createRouteBuilder() {
+ return new RouteBuilder() {
+ @Override
+ public void configure() {
+ // we use DLC to handle the exception but if it throw a new
exception
+ // then the DLC does NOT handle that (the transaction will
rollback)
+ errorHandler(deadLetterChannel("bean:" +
BadErrorHandler.class.getName())
+ .deadLetterHandleNewException(false)
+ .logNewException(true));
+
+ from(testingEndpoint)
+ .log("Incoming JMS message ${body}")
+ .throwException(new RuntimeCamelException("bad
error"));
+ }
+ };
+ }
+
@Test
public void shouldNotLoseMessagesOnExceptionInErrorHandler() {
template.sendBody(testingEndpoint, "Hello World");
// as we do not handle new exception, then the exception propagates
back
- // and causes the transaction to rollback, and we can find the message
in the ActiveMQ DLQ
- Object dlqBody = consumer.receiveBody("activemq:DLQ", 2000);
+ // and causes the transaction to rollback, and we can find the message
in the DLQ
+ Object dlqBody = consumer.receiveBody("activemq:" + DLQ_NAME, 30000);
assertEquals("Hello World", dlqBody);
}
+ @Override
+ protected CamelContext createCamelContext() throws Exception {
+ CamelContext camelContext = super.createCamelContext();
+
+ ConnectionFactory connectionFactory =
ConnectionFactoryHelper.createConnectionFactory(service, 0);
+
+ JmsComponent component = jmsComponentTransacted(connectionFactory);
+ camelContext.addComponent("activemq", component);
+ return camelContext;
+ }
+
}
diff --git
a/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/tx/JmsTransactedOnExceptionRollbackOnExceptionIT.java
b/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/tx/JmsTransactedOnExceptionRollbackOnExceptionIT.java
index 4580a39ba0ec..0b8a70c35b2d 100644
---
a/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/tx/JmsTransactedOnExceptionRollbackOnExceptionIT.java
+++
b/components/camel-jms/src/test/java/org/apache/camel/component/jms/integration/tx/JmsTransactedOnExceptionRollbackOnExceptionIT.java
@@ -18,6 +18,9 @@ package org.apache.camel.component.jms.integration.tx;
import jakarta.jms.ConnectionFactory;
+import org.apache.activemq.artemis.api.core.QueueConfiguration;
+import org.apache.activemq.artemis.api.core.RoutingType;
+import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.camel.CamelContext;
import org.apache.camel.Exchange;
import org.apache.camel.Handler;
@@ -26,7 +29,7 @@ import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.jms.JmsComponent;
import org.apache.camel.test.infra.artemis.common.ConnectionFactoryHelper;
import org.apache.camel.test.infra.artemis.services.ArtemisService;
-import org.apache.camel.test.infra.artemis.services.ArtemisServiceFactory;
+import org.apache.camel.test.infra.artemis.services.ArtemisVMService;
import org.apache.camel.test.junit6.CamelTestSupport;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Tags;
@@ -36,11 +39,27 @@ import org.junit.jupiter.api.extension.RegisterExtension;
import static
org.apache.camel.component.jms.JmsComponent.jmsComponentTransacted;
import static org.junit.jupiter.api.Assertions.assertEquals;
-// This test cannot run in parallel: it reads from the default DLQ and there
could be more messages there
@Tags({ @Tag("not-parallel"), @Tag("transaction") })
public class JmsTransactedOnExceptionRollbackOnExceptionIT extends
CamelTestSupport {
+
+ private static final String DLQ_NAME = "DLQ." +
JmsTransactedOnExceptionRollbackOnExceptionIT.class.getSimpleName();
+
@RegisterExtension
- public static ArtemisService service =
ArtemisServiceFactory.createVMService();
+ public static ArtemisService service = createArtemisService();
+
+ static ArtemisService createArtemisService() {
+ ArtemisVMService svc = new ArtemisVMService();
+ svc.customConfiguration(cfg -> {
+ cfg.getAddressSettings().values()
+ .forEach(s -> {
+ s.setMaxDeliveryAttempts(1);
+ s.setDeadLetterAddress(SimpleString.of(DLQ_NAME));
+ });
+ cfg.addQueueConfiguration(
+
QueueConfiguration.of(DLQ_NAME).setRoutingType(RoutingType.ANYCAST));
+ });
+ return svc;
+ }
public static class BadErrorHandler {
@@ -73,7 +92,7 @@ public class JmsTransactedOnExceptionRollbackOnExceptionIT
extends CamelTestSupp
public void shouldNotLoseMessagesOnExceptionInErrorHandler() throws
Exception {
template.sendBody(testingEndpoint, "Hello World");
- Object dlqBody = consumer.receiveBody("activemq:DLQ", 2000);
+ Object dlqBody = consumer.receiveBody("activemq:" + DLQ_NAME, 30000);
assertEquals("Hello World", dlqBody);
}
@@ -82,7 +101,6 @@ public class JmsTransactedOnExceptionRollbackOnExceptionIT
extends CamelTestSupp
protected CamelContext createCamelContext() throws Exception {
CamelContext camelContext = super.createCamelContext();
- // no redeliveries
ConnectionFactory connectionFactory =
ConnectionFactoryHelper.createConnectionFactory(service, 0);
JmsComponent component = jmsComponentTransacted(connectionFactory);
diff --git
a/components/camel-jms/src/test/java/org/apache/camel/component/jms/support/MyCoolBean.java
b/components/camel-jms/src/test/java/org/apache/camel/component/jms/support/MyCoolBean.java
index d0fb3df3eff4..76fd0bb13c1b 100644
---
a/components/camel-jms/src/test/java/org/apache/camel/component/jms/support/MyCoolBean.java
+++
b/components/camel-jms/src/test/java/org/apache/camel/component/jms/support/MyCoolBean.java
@@ -40,9 +40,9 @@ public final class MyCoolBean {
public void someBusinessLogic() {
// loop to empty queue
while (true) {
- // receive the message from the queue, wait at most 2 sec
+ // receive the message from the queue, wait at most 5 sec
try {
- String msg = consumer.receiveBody("activemq:" + queueName +
".in", 2000, String.class);
+ String msg = consumer.receiveBody("activemq:" + queueName +
".in", 5000, String.class);
if (msg == null) {
// no more messages in queue
break;
diff --git
a/test-infra/camel-test-infra-artemis/src/main/java/org/apache/camel/test/infra/artemis/services/AbstractArtemisEmbeddedService.java
b/test-infra/camel-test-infra-artemis/src/main/java/org/apache/camel/test/infra/artemis/services/AbstractArtemisEmbeddedService.java
index 41bf9b4b0f88..6aab1711c47d 100644
---
a/test-infra/camel-test-infra-artemis/src/main/java/org/apache/camel/test/infra/artemis/services/AbstractArtemisEmbeddedService.java
+++
b/test-infra/camel-test-infra-artemis/src/main/java/org/apache/camel/test/infra/artemis/services/AbstractArtemisEmbeddedService.java
@@ -19,7 +19,7 @@ package org.apache.camel.test.infra.artemis.services;
import java.io.File;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.LongAdder;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import jakarta.jms.ConnectionFactory;
@@ -42,7 +42,7 @@ import org.slf4j.LoggerFactory;
public abstract class AbstractArtemisEmbeddedService implements
ArtemisInfraService, ConnectionFactoryAware {
protected static final Logger LOG =
LoggerFactory.getLogger(AbstractArtemisEmbeddedService.class);
- private static final LongAdder BROKER_COUNT = new LongAdder();
+ private static final AtomicInteger BROKER_COUNT = new AtomicInteger();
protected final EmbeddedActiveMQ embeddedBrokerService;
private final Configuration artemisConfiguration;
@@ -107,9 +107,7 @@ public abstract class AbstractArtemisEmbeddedService
implements ArtemisInfraServ
* @return the broker ID to use
*/
protected int computeBrokerId() {
- final int brokerId = BROKER_COUNT.intValue();
- BROKER_COUNT.increment();
- return brokerId;
+ return BROKER_COUNT.getAndIncrement();
}
private static File createInstance(int brokerId) {
@@ -171,7 +169,9 @@ public abstract class AbstractArtemisEmbeddedService
implements ArtemisInfraServ
embeddedBrokerService.start();
-
embeddedBrokerService.getActiveMQServer().waitForActivation(20,
TimeUnit.SECONDS);
+ if
(!embeddedBrokerService.getActiveMQServer().waitForActivation(20,
TimeUnit.SECONDS)) {
+ LOG.warn("Artemis broker did not activate within 20
seconds, proceeding anyway");
+ }
}
} catch (Exception e) {
LOG.warn("Unable to start embedded Artemis broker: {}",
e.getMessage(), e);