Skip to content

Commit 998ed51

Browse files
committed
Add support for configuring JMS listener sessionTransacted
This commit introduces `spring.jms.listener.session-transacted` property in order to enable explicit configuration of `sessionTransacted` on the `DefaultMessageListenerContainer`. Prior to this commit, `sessionTransacted` would be configured implicitly based on presence of `JtaTransactionManager`.
1 parent ee9c745 commit 998ed51

File tree

3 files changed

+48
-5
lines changed

3 files changed

+48
-5
lines changed

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/DefaultJmsListenerContainerFactoryConfigurer.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2021 the original author or authors.
2+
* Copyright 2012-2023 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -32,6 +32,7 @@
3232
*
3333
* @author Stephane Nicoll
3434
* @author Eddú Meléndez
35+
* @author Vedran Pavic
3536
* @since 1.3.3
3637
*/
3738
public final class DefaultJmsListenerContainerFactoryConfigurer {
@@ -101,12 +102,16 @@ public void configure(DefaultJmsListenerContainerFactory factory, ConnectionFact
101102
Assert.notNull(connectionFactory, "ConnectionFactory must not be null");
102103
factory.setConnectionFactory(connectionFactory);
103104
factory.setPubSubDomain(this.jmsProperties.isPubSubDomain());
105+
JmsProperties.Listener listener = this.jmsProperties.getListener();
104106
if (this.transactionManager != null) {
105107
factory.setTransactionManager(this.transactionManager);
106108
}
107-
else {
109+
else if (listener.getSessionTransacted() == null) {
108110
factory.setSessionTransacted(true);
109111
}
112+
if (listener.getSessionTransacted() != null) {
113+
factory.setSessionTransacted(listener.getSessionTransacted());
114+
}
110115
if (this.destinationResolver != null) {
111116
factory.setDestinationResolver(this.destinationResolver);
112117
}
@@ -116,7 +121,6 @@ public void configure(DefaultJmsListenerContainerFactory factory, ConnectionFact
116121
if (this.exceptionListener != null) {
117122
factory.setExceptionListener(this.exceptionListener);
118123
}
119-
JmsProperties.Listener listener = this.jmsProperties.getListener();
120124
factory.setAutoStartup(listener.isAutoStartup());
121125
if (listener.getAcknowledgeMode() != null) {
122126
factory.setSessionAcknowledgeMode(listener.getAcknowledgeMode().getMode());

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsProperties.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
* @author Greg Turnquist
2828
* @author Phillip Webb
2929
* @author Stephane Nicoll
30+
* @author Vedran Pavic
3031
* @since 1.0.0
3132
*/
3233
@ConfigurationProperties(prefix = "spring.jms")
@@ -146,6 +147,11 @@ public static class Listener {
146147
*/
147148
private AcknowledgeMode acknowledgeMode;
148149

150+
/**
151+
* Whether the container should use transacted JMS sessions.
152+
*/
153+
private Boolean sessionTransacted;
154+
149155
/**
150156
* Minimum number of concurrent consumers. When max-concurrency is not specified
151157
* the minimum will also be used as the maximum.
@@ -180,6 +186,14 @@ public void setAcknowledgeMode(AcknowledgeMode acknowledgeMode) {
180186
this.acknowledgeMode = acknowledgeMode;
181187
}
182188

189+
public Boolean getSessionTransacted() {
190+
return this.sessionTransacted;
191+
}
192+
193+
public void setSessionTransacted(Boolean sessionTransacted) {
194+
this.sessionTransacted = sessionTransacted;
195+
}
196+
183197
@DeprecatedConfigurationProperty(replacement = "spring.jms.listener.min-concurrency", since = "3.2.0")
184198
@Deprecated(since = "3.2.0", forRemoval = true)
185199
public Integer getConcurrency() {

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/JmsAutoConfigurationTests.java

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
* @author Stephane Nicoll
5858
* @author Aurélien Leboulanger
5959
* @author Eddú Meléndez
60+
* @author Vedran Pavic
6061
*/
6162
class JmsAutoConfigurationTests {
6263

@@ -143,15 +144,16 @@ void jmsListenerContainerFactoryWhenMultipleConnectionFactoryBeansShouldBackOff(
143144
void testJmsListenerContainerFactoryWithCustomSettings() {
144145
this.contextRunner.withUserConfiguration(EnableJmsConfiguration.class)
145146
.withPropertyValues("spring.jms.listener.autoStartup=false", "spring.jms.listener.acknowledgeMode=client",
146-
"spring.jms.listener.minConcurrency=2", "spring.jms.listener.receiveTimeout=2s",
147-
"spring.jms.listener.maxConcurrency=10")
147+
"spring.jms.listener.sessionTransacted=false", "spring.jms.listener.minConcurrency=2",
148+
"spring.jms.listener.receiveTimeout=2s", "spring.jms.listener.maxConcurrency=10")
148149
.run(this::testJmsListenerContainerFactoryWithCustomSettings);
149150
}
150151

151152
private void testJmsListenerContainerFactoryWithCustomSettings(AssertableApplicationContext loaded) {
152153
DefaultMessageListenerContainer container = getContainer(loaded, "jmsListenerContainerFactory");
153154
assertThat(container.isAutoStartup()).isFalse();
154155
assertThat(container.getSessionAcknowledgeMode()).isEqualTo(Session.CLIENT_ACKNOWLEDGE);
156+
assertThat(container.isSessionTransacted()).isFalse();
155157
assertThat(container.getConcurrentConsumers()).isEqualTo(2);
156158
assertThat(container.getMaxConcurrentConsumers()).isEqualTo(10);
157159
assertThat(container).hasFieldOrPropertyWithValue("receiveTimeout", 2000L);
@@ -179,6 +181,18 @@ void testDefaultContainerFactoryWithJtaTransactionManager() {
179181
});
180182
}
181183

184+
@Test
185+
void testDefaultContainerFactoryWithJtaTransactionManagerAndSessionTransactedEnabled() {
186+
this.contextRunner.withUserConfiguration(TestConfiguration7.class, EnableJmsConfiguration.class)
187+
.withPropertyValues("spring.jms.listener.sessionTransacted=true")
188+
.run((context) -> {
189+
DefaultMessageListenerContainer container = getContainer(context, "jmsListenerContainerFactory");
190+
assertThat(container.isSessionTransacted()).isTrue();
191+
assertThat(container).hasFieldOrPropertyWithValue("transactionManager",
192+
context.getBean(JtaTransactionManager.class));
193+
});
194+
}
195+
182196
@Test
183197
void testDefaultContainerFactoryNonJtaTransactionManager() {
184198
this.contextRunner.withUserConfiguration(TestConfiguration8.class, EnableJmsConfiguration.class)
@@ -198,6 +212,17 @@ void testDefaultContainerFactoryNoTransactionManager() {
198212
});
199213
}
200214

215+
@Test
216+
void testDefaultContainerFactoryNoTransactionManagerAndSessionTransactedDisabled() {
217+
this.contextRunner.withUserConfiguration(EnableJmsConfiguration.class)
218+
.withPropertyValues("spring.jms.listener.sessionTransacted=false")
219+
.run((context) -> {
220+
DefaultMessageListenerContainer container = getContainer(context, "jmsListenerContainerFactory");
221+
assertThat(container.isSessionTransacted()).isFalse();
222+
assertThat(container).hasFieldOrPropertyWithValue("transactionManager", null);
223+
});
224+
}
225+
201226
@Test
202227
void testDefaultContainerFactoryWithMessageConverters() {
203228
this.contextRunner.withUserConfiguration(MessageConvertersConfiguration.class, EnableJmsConfiguration.class)

0 commit comments

Comments
 (0)