diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsAutoConfiguration.java index 814bab4338..d4252939b1 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsAutoConfiguration.java @@ -17,6 +17,7 @@ package org.springframework.boot.autoconfigure.jms; import javax.jms.ConnectionFactory; +import javax.jms.Message; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; @@ -40,7 +41,7 @@ import org.springframework.jms.support.destination.DestinationResolver; * @author Stephane Nicoll */ @Configuration -@ConditionalOnClass(JmsTemplate.class) +@ConditionalOnClass({Message.class, JmsTemplate.class}) @ConditionalOnBean(ConnectionFactory.class) @EnableConfigurationProperties(JmsProperties.class) @Import(JmsAnnotationDrivenConfiguration.class) @@ -78,8 +79,27 @@ public class JmsAutoConfiguration { if (messageConverter != null) { jmsTemplate.setMessageConverter(messageConverter); } + JmsProperties.Template template = this.properties.getTemplate(); + if (template.getDefaultDestination() != null) { + jmsTemplate.setDefaultDestinationName(template.getDefaultDestination()); + } + if (template.getDeliveryDelay() != null) { + jmsTemplate.setDeliveryDelay(template.getDeliveryDelay()); + } + jmsTemplate.setExplicitQosEnabled(template.determineQosEnabled()); + if (template.getDeliveryMode() != null) { + jmsTemplate.setDeliveryMode(template.getDeliveryMode().getValue()); + } + if (template.getPriority() != null) { + jmsTemplate.setPriority(template.getPriority()); + } + if (template.getTimeToLive() != null) { + jmsTemplate.setTimeToLive(template.getTimeToLive()); + } + if (template.getReceiveTimeout() != null) { + jmsTemplate.setReceiveTimeout(template.getReceiveTimeout()); + } return jmsTemplate; - } } diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsProperties.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsProperties.java index ac28329c7b..eb5e7d6684 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsProperties.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsProperties.java @@ -41,6 +41,8 @@ public class JmsProperties { private final Listener listener = new Listener(); + private final Template template = new Template(); + public boolean isPubSubDomain() { return this.pubSubDomain; } @@ -61,6 +63,10 @@ public class JmsProperties { return this.listener; } + public Template getTemplate() { + return this.template; + } + public static class Listener { /** @@ -126,6 +132,114 @@ public class JmsProperties { } } + public static class Template { + + /** + * Default destination to use on send/receive operations that do not + * have a destination parameter. + */ + private String defaultDestination; + + /** + * Delivery delay to use for send calls in milliseconds. + */ + private Long deliveryDelay; + + /** + * Delivery mode. Enable QoS when set. + */ + private DeliveryMode deliveryMode; + + /** + * Priority of a message when sending. Enable QoS when set. + */ + private Integer priority; + + /** + * Time-to-live of a message when sending in milliseconds. Enable + * QoS when set. + */ + private Long timeToLive; + + /** + * Enable explicit QoS when sending a message. When enabled, the + * delivery mode, priority and time-to-live properties will be + * used when sending a message. QoS is automatically enabled when + * at least one of those settings is customized. + */ + private Boolean qosEnabled; + + /** + * Timeout to use for receive calls in milliseconds. + */ + private Long receiveTimeout; + + public String getDefaultDestination() { + return this.defaultDestination; + } + + public void setDefaultDestination(String defaultDestination) { + this.defaultDestination = defaultDestination; + } + + public Long getDeliveryDelay() { + return this.deliveryDelay; + } + + public void setDeliveryDelay(Long deliveryDelay) { + this.deliveryDelay = deliveryDelay; + } + + public DeliveryMode getDeliveryMode() { + return this.deliveryMode; + } + + public void setDeliveryMode(DeliveryMode deliveryMode) { + this.deliveryMode = deliveryMode; + } + + public Integer getPriority() { + return this.priority; + } + + public void setPriority(Integer priority) { + this.priority = priority; + } + + public Long getTimeToLive() { + return this.timeToLive; + } + + public void setTimeToLive(Long timeToLive) { + this.timeToLive = timeToLive; + } + + public boolean determineQosEnabled() { + if (this.qosEnabled != null) { + return this.qosEnabled; + } + return (getDeliveryMode() != null || getPriority() != null + || getTimeToLive() != null); + } + + public Boolean getQosEnabled() { + return this.qosEnabled; + } + + public void setQosEnabled(Boolean qosEnabled) { + this.qosEnabled = qosEnabled; + } + + public Long getReceiveTimeout() { + return this.receiveTimeout; + } + + public void setReceiveTimeout(Long receiveTimeout) { + this.receiveTimeout = receiveTimeout; + } + + } + /** * Translate the acknowledge modes defined on the {@link javax.jms.Session}. * @@ -164,6 +278,34 @@ public class JmsProperties { public int getMode() { return this.mode; } + + } + + public enum DeliveryMode { + + /** + * Does not require that the message be logged to stable storage. This is the + * lowest-overhead delivery mode but can lead to lost of message if the broker + * goes down. + */ + NON_PERSISTENT(1), + + /* + * Instructs the JMS provider to log the message to stable storage as part of + * the client's send operation. + */ + PERSISTENT(2); + + private final int value; + + DeliveryMode(int value) { + this.value = value; + } + + public int getValue() { + return this.value; + } + } } diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/JmsAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/JmsAutoConfigurationTests.java index 3ec1efa930..1e81850a7f 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/JmsAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/JmsAutoConfigurationTests.java @@ -44,6 +44,7 @@ import org.springframework.jms.core.JmsMessagingTemplate; import org.springframework.jms.core.JmsTemplate; import org.springframework.jms.listener.DefaultMessageListenerContainer; import org.springframework.jms.support.converter.MessageConverter; +import org.springframework.jms.support.destination.DestinationResolver; import org.springframework.transaction.jta.JtaTransactionManager; import static org.assertj.core.api.Assertions.assertThat; @@ -237,13 +238,43 @@ public class JmsAutoConfigurationTests { } @Test - public void testJmsTemplateWithMessageConverters() { + public void testJmsTemplateWithMessageConverter() { load(MessageConvertersConfiguration.class); JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class); assertThat(jmsTemplate.getMessageConverter()) .isSameAs(this.context.getBean("myMessageConverter")); } + @Test + public void testJmsTemplateWithDestinationResolver() { + load(DestinationResolversConfiguration.class); + JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class); + assertThat(jmsTemplate.getDestinationResolver()) + .isSameAs(this.context.getBean("myDestinationResolver")); + } + + @Test + public void testJmsTemplateFullCustomization() { + load(MessageConvertersConfiguration.class, + "spring.jms.template.default-destination=testQueue", + "spring.jms.template.delivery-delay=500", + "spring.jms.template.delivery-mode=non-persistent", + "spring.jms.template.priority=6", + "spring.jms.template.time-to-live=6000", + "spring.jms.template.receive-timeout=2000"); + JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class); + assertThat(jmsTemplate.getMessageConverter()) + .isSameAs(this.context.getBean("myMessageConverter")); + assertThat(jmsTemplate.isPubSubDomain()).isFalse(); + assertThat(jmsTemplate.getDefaultDestinationName()).isEqualTo("testQueue"); + assertThat(jmsTemplate.getDeliveryDelay()).isEqualTo(500); + assertThat(jmsTemplate.getDeliveryMode()).isEqualTo(1); + assertThat(jmsTemplate.getPriority()).isEqualTo(6); + assertThat(jmsTemplate.getTimeToLive()).isEqualTo(6000); + assertThat(jmsTemplate.isExplicitQosEnabled()).isTrue(); + assertThat(jmsTemplate.getReceiveTimeout()).isEqualTo(2000); + } + @Test public void testPubSubDisabledByDefault() { load(TestConfiguration.class); @@ -493,6 +524,22 @@ public class JmsAutoConfigurationTests { } + @Configuration + protected static class DestinationResolversConfiguration { + + @Bean + @Primary + public DestinationResolver myDestinationResolver() { + return mock(DestinationResolver.class); + } + + @Bean + public DestinationResolver anotherDestinationResolver() { + return mock(DestinationResolver.class); + } + + } + @Configuration protected static class TestConfiguration9 { diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/JmsPropertiesTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/JmsPropertiesTests.java index 766b29928e..6eef27727a 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/JmsPropertiesTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/JmsPropertiesTests.java @@ -55,4 +55,25 @@ public class JmsPropertiesTests { assertThat(properties.getListener().formatConcurrency()).isEqualTo("2-10"); } + @Test + public void setDeliveryModeEnablesQoS() { + JmsProperties properties = new JmsProperties(); + properties.getTemplate().setDeliveryMode(JmsProperties.DeliveryMode.PERSISTENT); + assertThat(properties.getTemplate().determineQosEnabled()).isTrue(); + } + + @Test + public void setPriorityEnablesQoS() { + JmsProperties properties = new JmsProperties(); + properties.getTemplate().setPriority(6); + assertThat(properties.getTemplate().determineQosEnabled()).isTrue(); + } + + @Test + public void setTimeToLiveEnablesQoS() { + JmsProperties properties = new JmsProperties(); + properties.getTemplate().setTimeToLive(5000L); + assertThat(properties.getTemplate().determineQosEnabled()).isTrue(); + } + } diff --git a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc index 561b097b88..950ac8bcc9 100644 --- a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc +++ b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc @@ -838,6 +838,13 @@ content into your application; rather pick only the properties that you need. spring.jms.listener.concurrency= # Minimum number of concurrent consumers. spring.jms.listener.max-concurrency= # Maximum number of concurrent consumers. spring.jms.pub-sub-domain=false # Specify if the default destination type is topic. + spring.jms.template.default-destination= # Default destination to use on send/receive operations that do not have a destination parameter. + spring.jms.template.delivery-delay= # Delivery delay to use for send calls in milliseconds. + spring.jms.template.delivery-mode= # Delivery mode. Enable QoS when set. + spring.jms.template.priority= # Priority of a message when sending. Enable QoS when set. + spring.jms.template.qos-enabled= # Enable explicit QoS when sending a message. + spring.jms.template.receive-timeout= # Timeout to use for receive calls in milliseconds. + spring.jms.template.time-to-live= # Time-to-live of a message when sending in milliseconds. Enable QoS when set. # RABBIT ({sc-spring-boot-autoconfigure}/amqp/RabbitProperties.{sc-ext}[RabbitProperties]) spring.rabbitmq.addresses= # Comma-separated list of addresses to which the client should connect.