From 1cde6578612ba99f51d02a066ba4d7fca9e90755 Mon Sep 17 00:00:00 2001 From: ibmmqmet Date: Thu, 27 Jun 2019 09:16:39 +0100 Subject: [PATCH 1/2] Add a config property for JMS listener container's receive timeout See gh-17332 --- ...ultJmsListenerContainerFactoryConfigurer.java | 6 ++++++ .../boot/autoconfigure/jms/JmsProperties.java | 16 ++++++++++++++++ .../jms/JmsAutoConfigurationTests.java | 14 +++++++++++++- 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/DefaultJmsListenerContainerFactoryConfigurer.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/DefaultJmsListenerContainerFactoryConfigurer.java index 414ead5b7a..ccb1f730b0 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/DefaultJmsListenerContainerFactoryConfigurer.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/DefaultJmsListenerContainerFactoryConfigurer.java @@ -16,6 +16,8 @@ package org.springframework.boot.autoconfigure.jms; +import java.time.Duration; + import javax.jms.ConnectionFactory; import org.springframework.jms.config.DefaultJmsListenerContainerFactory; @@ -107,6 +109,10 @@ public final class DefaultJmsListenerContainerFactoryConfigurer { if (concurrency != null) { factory.setConcurrency(concurrency); } + Duration receiveTimeout = listener.getReceiveTimeout(); + if (receiveTimeout != null) { + factory.setReceiveTimeout(receiveTimeout.toMillis()); + } } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsProperties.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsProperties.java index 63d15ac1ca..14e24d36ea 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsProperties.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsProperties.java @@ -155,6 +155,14 @@ public class JmsProperties { */ private Integer maxConcurrency; + /** + * Timeout to use for receive calls. By default, the listener uses a 1s timeout on + * its polling loop. See + * @see org.springframework.jms.listener.AbstractPollingMessageListenerContainer#setReceiveTimeout + * for more details on this value and the meaning of special values 0 and -1. + */ + private Duration receiveTimeout; + public boolean isAutoStartup() { return this.autoStartup; } @@ -195,6 +203,14 @@ public class JmsProperties { : String.valueOf(this.concurrency)); } + public Duration getReceiveTimeout() { + return this.receiveTimeout; + } + + public void setReceiveTimeout(Duration receiveTimeout) { + this.receiveTimeout = receiveTimeout; + } + } public static class Template { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/JmsAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/JmsAutoConfigurationTests.java index af7352db90..4989e3ce0f 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/JmsAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/JmsAutoConfigurationTests.java @@ -147,7 +147,7 @@ class JmsAutoConfigurationTests { this.contextRunner.withUserConfiguration(EnableJmsConfiguration.class) .withPropertyValues("spring.jms.listener.autoStartup=false", "spring.jms.listener.acknowledgeMode=client", "spring.jms.listener.concurrency=2", - "spring.jms.listener.maxConcurrency=10") + "spring.jms.listener.receiveTimeout=2s", "spring.jms.listener.maxConcurrency=10") .run(this::testJmsListenerContainerFactoryWithCustomSettings); } @@ -157,6 +157,18 @@ class JmsAutoConfigurationTests { assertThat(container.getSessionAcknowledgeMode()).isEqualTo(Session.CLIENT_ACKNOWLEDGE); assertThat(container.getConcurrentConsumers()).isEqualTo(2); assertThat(container.getMaxConcurrentConsumers()).isEqualTo(10); + assertThat(container).hasFieldOrPropertyWithValue("receiveTimeout", 2000L); + } + + @Test + void testJmsListenerContainerFactoryWithDefaultSettings() { + this.contextRunner.withUserConfiguration(EnableJmsConfiguration.class) + .run(this::testJmsListenerContainerFactoryWithDefaultSettings); + } + + private void testJmsListenerContainerFactoryWithDefaultSettings(AssertableApplicationContext loaded) { + DefaultMessageListenerContainer container = getContainer(loaded, "jmsListenerContainerFactory"); + assertThat(container).hasFieldOrPropertyWithValue("receiveTimeout", 1000L); } @Test From 1f875d552ac98353d6c6eabeb8473772414d0a77 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 5 Sep 2019 21:41:47 +0100 Subject: [PATCH 2/2] Polish "Add a config property for JMS listener container's receive timeout" See gh-17332 --- .../boot/autoconfigure/jms/JmsProperties.java | 9 ++++----- .../boot/autoconfigure/jms/JmsPropertiesTests.java | 8 ++++++++ 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsProperties.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsProperties.java index 14e24d36ea..aafab7c8fd 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsProperties.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsProperties.java @@ -156,12 +156,11 @@ public class JmsProperties { private Integer maxConcurrency; /** - * Timeout to use for receive calls. By default, the listener uses a 1s timeout on - * its polling loop. See - * @see org.springframework.jms.listener.AbstractPollingMessageListenerContainer#setReceiveTimeout - * for more details on this value and the meaning of special values 0 and -1. + * Timeout to use for receive calls. Use -1 for a no-wait receive or 0 for no + * timeout at all. The latter is only feasible if not running within a transaction + * manager and is generally discouraged since it prevents clean shutdown. */ - private Duration receiveTimeout; + private Duration receiveTimeout = Duration.ofSeconds(1); public boolean isAutoStartup() { return this.autoStartup; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/JmsPropertiesTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/JmsPropertiesTests.java index ae4d4ac54b..2f339d7670 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/JmsPropertiesTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/JmsPropertiesTests.java @@ -20,6 +20,8 @@ import java.time.Duration; import org.junit.jupiter.api.Test; +import org.springframework.jms.listener.AbstractPollingMessageListenerContainer; + import static org.assertj.core.api.Assertions.assertThat; /** @@ -78,4 +80,10 @@ class JmsPropertiesTests { assertThat(properties.getTemplate().determineQosEnabled()).isTrue(); } + @Test + void defaultReceiveTimeoutMatchesListenerContainersDefault() { + assertThat(new JmsProperties().getListener().getReceiveTimeout()) + .isEqualTo(Duration.ofMillis(AbstractPollingMessageListenerContainer.DEFAULT_RECEIVE_TIMEOUT)); + } + }