Skip to content

Commit 79e2cb3

Browse files
vpavicwilkinsona
authored andcommitted
Add config prop for JMS listener's sessionTransacted flag
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`. See spring-projectsgh-37473
1 parent b7facec commit 79e2cb3

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
factory.setSessionAcknowledgeMode(listener.getSession().getAcknowledgeMode().getMode());
122126
String concurrency = listener.formatConcurrency();

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,11 @@ public static class Listener {
141141
*/
142142
private boolean autoStartup = true;
143143

144+
/**
145+
* Whether the container should use transacted JMS sessions.
146+
*/
147+
private Boolean sessionTransacted;
148+
144149
/**
145150
* Minimum number of concurrent consumers. When max-concurrency is not specified
146151
* the minimum will also be used as the maximum.
@@ -180,6 +185,14 @@ public void setAcknowledgeMode(AcknowledgeMode acknowledgeMode) {
180185
this.session.setAcknowledgeMode(acknowledgeMode);
181186
}
182187

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

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

Lines changed: 28 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,17 @@ void jmsListenerContainerFactoryWhenMultipleConnectionFactoryBeansShouldBackOff(
143144
void testJmsListenerContainerFactoryWithCustomSettings() {
144145
this.contextRunner.withUserConfiguration(EnableJmsConfiguration.class)
145146
.withPropertyValues("spring.jms.listener.autoStartup=false",
146-
"spring.jms.listener.session.acknowledgeMode=client", "spring.jms.listener.minConcurrency=2",
147-
"spring.jms.listener.receiveTimeout=2s", "spring.jms.listener.maxConcurrency=10")
147+
"spring.jms.listener.session.acknowledgeMode=client", "spring.jms.listener.sessionTransacted=false",
148+
"spring.jms.listener.minConcurrency=2", "spring.jms.listener.receiveTimeout=2s",
149+
"spring.jms.listener.maxConcurrency=10")
148150
.run(this::testJmsListenerContainerFactoryWithCustomSettings);
149151
}
150152

151153
private void testJmsListenerContainerFactoryWithCustomSettings(AssertableApplicationContext loaded) {
152154
DefaultMessageListenerContainer container = getContainer(loaded, "jmsListenerContainerFactory");
153155
assertThat(container.isAutoStartup()).isFalse();
154156
assertThat(container.getSessionAcknowledgeMode()).isEqualTo(Session.CLIENT_ACKNOWLEDGE);
157+
assertThat(container.isSessionTransacted()).isFalse();
155158
assertThat(container.getConcurrentConsumers()).isEqualTo(2);
156159
assertThat(container.getMaxConcurrentConsumers()).isEqualTo(10);
157160
assertThat(container).hasFieldOrPropertyWithValue("receiveTimeout", 2000L);
@@ -179,6 +182,18 @@ void testDefaultContainerFactoryWithJtaTransactionManager() {
179182
});
180183
}
181184

185+
@Test
186+
void testDefaultContainerFactoryWithJtaTransactionManagerAndSessionTransactedEnabled() {
187+
this.contextRunner.withUserConfiguration(TestConfiguration7.class, EnableJmsConfiguration.class)
188+
.withPropertyValues("spring.jms.listener.sessionTransacted=true")
189+
.run((context) -> {
190+
DefaultMessageListenerContainer container = getContainer(context, "jmsListenerContainerFactory");
191+
assertThat(container.isSessionTransacted()).isTrue();
192+
assertThat(container).hasFieldOrPropertyWithValue("transactionManager",
193+
context.getBean(JtaTransactionManager.class));
194+
});
195+
}
196+
182197
@Test
183198
void testDefaultContainerFactoryNonJtaTransactionManager() {
184199
this.contextRunner.withUserConfiguration(TestConfiguration8.class, EnableJmsConfiguration.class)
@@ -198,6 +213,17 @@ void testDefaultContainerFactoryNoTransactionManager() {
198213
});
199214
}
200215

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

0 commit comments

Comments
 (0)