diff --git a/spring-boot-autoconfigure/pom.xml b/spring-boot-autoconfigure/pom.xml
index 22b8d1f14a..309b5d597b 100644
--- a/spring-boot-autoconfigure/pom.xml
+++ b/spring-boot-autoconfigure/pom.xml
@@ -31,6 +31,11 @@
activemq-core
true
+
+ org.apache.activemq
+ activemq-pool
+ true
+
org.apache.tomcat.embed
tomcat-embed-core
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsTemplateAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsTemplateAutoConfiguration.java
index 46a387c5a1..464b7312f5 100644
--- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsTemplateAutoConfiguration.java
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsTemplateAutoConfiguration.java
@@ -19,10 +19,13 @@ package org.springframework.boot.autoconfigure.jms;
import javax.jms.ConnectionFactory;
import org.apache.activemq.ActiveMQConnectionFactory;
+import org.apache.activemq.pool.PooledConnectionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.core.JmsTemplate;
@@ -38,7 +41,11 @@ public class JmsTemplateAutoConfiguration {
@Configuration
@ConditionalOnMissingBean(JmsTemplate.class)
+ @EnableConfigurationProperties(JmsTemplateProperties.class)
protected static class JmsTemplateCreator {
+
+ @Autowired
+ private JmsTemplateProperties config;
@Autowired
private ConnectionFactory connectionFactory;
@@ -46,22 +53,87 @@ public class JmsTemplateAutoConfiguration {
@Bean
public JmsTemplate jmsTemplate() {
JmsTemplate jmsTemplate = new JmsTemplate(this.connectionFactory);
- jmsTemplate.setPubSubDomain(true);
+ jmsTemplate.setPubSubDomain(this.config.isPubSubDomain());
return jmsTemplate;
}
}
+
+ @ConfigurationProperties(name = "spring.jms")
+ public static class JmsTemplateProperties {
+
+ private boolean pubSubDomain = true;
+
+ public boolean isPubSubDomain() {
+ return pubSubDomain;
+ }
+
+ public void setPubSubDomain(boolean pubSubDomain) {
+ this.pubSubDomain = pubSubDomain;
+ }
+
+ }
@Configuration
@ConditionalOnClass(ActiveMQConnectionFactory.class)
@ConditionalOnMissingBean(ConnectionFactory.class)
+ @EnableConfigurationProperties(ActiveMQConnectionFactoryProperties.class)
protected static class ActiveMQConnectionFactoryCreator {
-
+
+ @Autowired
+ private ActiveMQConnectionFactoryProperties config;
+
@Bean
ConnectionFactory connectionFactory() {
- return new ActiveMQConnectionFactory("vm://localhost");
+ if (this.config.isPooled()) {
+ PooledConnectionFactory pool = new PooledConnectionFactory();
+ pool.setConnectionFactory(new ActiveMQConnectionFactory(this.config.getBrokerURL()));
+ return pool;
+ } else {
+ return new ActiveMQConnectionFactory(this.config.getBrokerURL());
+ }
+ }
+
+ }
+
+ @ConfigurationProperties(name = "spring.activemq")
+ public static class ActiveMQConnectionFactoryProperties {
+
+ private String brokerURL = "tcp://localhost:61616";
+
+ private boolean inMemory = true;
+
+ private boolean pooled = false;
+
+ // Will override brokerURL if inMemory is set to true
+ public String getBrokerURL() {
+ if (this.inMemory) {
+ return "vm://localhost";
+ } else {
+ return this.brokerURL;
+ }
+ }
+
+ public void setBrokerURL(String brokerURL) {
+ this.brokerURL = brokerURL;
+ }
+
+ public boolean isInMemory() {
+ return inMemory;
}
+ public void setInMemory(boolean inMemory) {
+ this.inMemory = inMemory;
+ }
+
+ public boolean isPooled() {
+ return pooled;
+ }
+
+ public void setPooled(boolean pooled) {
+ this.pooled = pooled;
+ }
+
}
}
diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/JmsTemplateAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/JmsTemplateAutoConfigurationTests.java
index c8c44df97b..d477ffcba8 100644
--- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/JmsTemplateAutoConfigurationTests.java
+++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/JmsTemplateAutoConfigurationTests.java
@@ -19,9 +19,11 @@ package org.springframework.boot.autoconfigure.jms;
import javax.jms.ConnectionFactory;
import org.apache.activemq.ActiveMQConnectionFactory;
+import org.apache.activemq.pool.PooledConnectionFactory;
import org.junit.Test;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
+import org.springframework.boot.TestUtils;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -53,6 +55,7 @@ public class JmsTemplateAutoConfigurationTests {
assertNotNull(jmsTemplate);
assertNotNull(connectionFactory);
assertEquals(jmsTemplate.getConnectionFactory(), connectionFactory);
+ assertEquals(((ActiveMQConnectionFactory)jmsTemplate.getConnectionFactory()).getBrokerURL(), "vm://localhost");
}
@Test
@@ -106,6 +109,110 @@ public class JmsTemplateAutoConfigurationTests {
JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class);
assertFalse(jmsTemplate.isPubSubDomain());
}
+
+ @Test
+ public void testJmsTemplateOverridden() {
+ this.context = new AnnotationConfigApplicationContext();
+ this.context
+ .register(TestConfiguration.class, JmsTemplateAutoConfiguration.class);
+ TestUtils.addEnviroment(this.context, "spring.jms.pubSubDomain:false");
+ this.context.refresh();
+ JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class);
+ ActiveMQConnectionFactory connectionFactory = this.context
+ .getBean(ActiveMQConnectionFactory.class);
+ assertNotNull(jmsTemplate);
+ assertFalse(jmsTemplate.isPubSubDomain());
+ assertNotNull(connectionFactory);
+ assertEquals(jmsTemplate.getConnectionFactory(), connectionFactory);
+ }
+
+ @Test
+ public void testActiveMQOverriddenStandalone() {
+ this.context = new AnnotationConfigApplicationContext();
+ this.context
+ .register(TestConfiguration.class, JmsTemplateAutoConfiguration.class);
+ TestUtils.addEnviroment(this.context, "spring.activemq.inMemory:false");
+ this.context.refresh();
+ JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class);
+ ActiveMQConnectionFactory connectionFactory = this.context
+ .getBean(ActiveMQConnectionFactory.class);
+ assertNotNull(jmsTemplate);
+ assertNotNull(connectionFactory);
+ assertEquals(jmsTemplate.getConnectionFactory(), connectionFactory);
+ assertEquals(((ActiveMQConnectionFactory)jmsTemplate.getConnectionFactory()).getBrokerURL(),
+ "tcp://localhost:61616");
+ }
+
+ @Test
+ public void testActiveMQOverriddenRemoteHost() {
+ this.context = new AnnotationConfigApplicationContext();
+ this.context
+ .register(TestConfiguration.class, JmsTemplateAutoConfiguration.class);
+ TestUtils.addEnviroment(this.context, "spring.activemq.inMemory:false",
+ "spring.activemq.brokerURL:tcp://remote-host:10000");
+ this.context.refresh();
+ JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class);
+ ActiveMQConnectionFactory connectionFactory = this.context
+ .getBean(ActiveMQConnectionFactory.class);
+ assertNotNull(jmsTemplate);
+ assertNotNull(connectionFactory);
+ assertEquals(jmsTemplate.getConnectionFactory(), connectionFactory);
+ assertEquals(((ActiveMQConnectionFactory)jmsTemplate.getConnectionFactory()).getBrokerURL(),
+ "tcp://remote-host:10000");
+ }
+
+ @Test
+ public void testActiveMQOverriddenPool() {
+ this.context = new AnnotationConfigApplicationContext();
+ this.context
+ .register(TestConfiguration.class, JmsTemplateAutoConfiguration.class);
+ TestUtils.addEnviroment(this.context, "spring.activemq.pooled:true");
+ this.context.refresh();
+ JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class);
+ PooledConnectionFactory pool = this.context
+ .getBean(PooledConnectionFactory.class);
+ assertNotNull(jmsTemplate);
+ assertNotNull(pool);
+ assertEquals(jmsTemplate.getConnectionFactory(), pool);
+ ActiveMQConnectionFactory factory = (ActiveMQConnectionFactory) pool.getConnectionFactory();
+ assertEquals("vm://localhost", factory.getBrokerURL());
+ }
+
+ @Test
+ public void testActiveMQOverriddenPoolAndStandalone() {
+ this.context = new AnnotationConfigApplicationContext();
+ this.context
+ .register(TestConfiguration.class, JmsTemplateAutoConfiguration.class);
+ TestUtils.addEnviroment(this.context, "spring.activemq.pooled:true",
+ "spring.activemq.inMemory:false");
+ this.context.refresh();
+ JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class);
+ PooledConnectionFactory pool = this.context
+ .getBean(PooledConnectionFactory.class);
+ assertNotNull(jmsTemplate);
+ assertNotNull(pool);
+ assertEquals(jmsTemplate.getConnectionFactory(), pool);
+ ActiveMQConnectionFactory factory = (ActiveMQConnectionFactory) pool.getConnectionFactory();
+ assertEquals("tcp://localhost:61616", factory.getBrokerURL());
+ }
+
+ @Test
+ public void testActiveMQOverriddenPoolAndRemoteServer() {
+ this.context = new AnnotationConfigApplicationContext();
+ this.context
+ .register(TestConfiguration.class, JmsTemplateAutoConfiguration.class);
+ TestUtils.addEnviroment(this.context, "spring.activemq.pooled:true",
+ "spring.activemq.inMemory:false", "spring.activemq.brokerURL:tcp://remote-host:10000");
+ this.context.refresh();
+ JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class);
+ PooledConnectionFactory pool = this.context
+ .getBean(PooledConnectionFactory.class);
+ assertNotNull(jmsTemplate);
+ assertNotNull(pool);
+ assertEquals(jmsTemplate.getConnectionFactory(), pool);
+ ActiveMQConnectionFactory factory = (ActiveMQConnectionFactory) pool.getConnectionFactory();
+ assertEquals("tcp://remote-host:10000", factory.getBrokerURL());
+ }
@Configuration
protected static class TestConfiguration {
diff --git a/spring-boot-cli/samples/jms.groovy b/spring-boot-cli/samples/jms.groovy
index 7e189b0498..df2a62d475 100644
--- a/spring-boot-cli/samples/jms.groovy
+++ b/spring-boot-cli/samples/jms.groovy
@@ -1,11 +1,13 @@
package org.test
@Grab("org.apache.activemq:activemq-all:5.4.0")
+@Grab("org.apache.activemq:activemq-pool:5.4.0")
import java.util.concurrent.CountDownLatch
-@Configuration
@Log
+@Configuration
+@EnableJmsMessaging
class JmsExample implements CommandLineRunner {
private CountDownLatch latch = new CountDownLatch(1)
@@ -30,7 +32,6 @@ class JmsExample implements CommandLineRunner {
session.createObjectMessage("Greetings from Spring Boot via ActiveMQ")
} as MessageCreator
log.info "Sending JMS message..."
- jmsTemplate.pubSubDomain = true
jmsTemplate.send("spring-boot", messageCreator)
latch.await()
}
diff --git a/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/autoconfigure/JmsCompilerAutoConfiguration.java b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/autoconfigure/JmsCompilerAutoConfiguration.java
index 5c6d47454a..c2182fad48 100644
--- a/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/autoconfigure/JmsCompilerAutoConfiguration.java
+++ b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/autoconfigure/JmsCompilerAutoConfiguration.java
@@ -23,6 +23,8 @@ import org.springframework.boot.cli.compiler.AstUtils;
import org.springframework.boot.cli.compiler.CompilerAutoConfiguration;
import org.springframework.boot.cli.compiler.DependencyCustomizer;
+import java.lang.annotation.*;
+
/**
* {@link CompilerAutoConfiguration} for Spring JMS.
*
@@ -32,8 +34,9 @@ public class JmsCompilerAutoConfiguration extends CompilerAutoConfiguration {
@Override
public boolean matches(ClassNode classNode) {
- return AstUtils.hasAtLeastOneFieldOrMethod(classNode, "JmsTemplate",
- "DefaultMessageListenerContainer", "SimpleMessageListenerContainer");
+ // Slightly weird detection algorithm because there is no @Enable annotation for
+ // Spring JMS
+ return AstUtils.hasAtLeastOneAnnotation(classNode, "EnableJmsMessaging");
}
@Override
@@ -49,7 +52,15 @@ public class JmsCompilerAutoConfiguration extends CompilerAutoConfiguration {
public void applyImports(ImportCustomizer imports) throws CompilationFailedException {
imports.addStarImports("javax.jms", "org.springframework.jms.core",
"org.springframework.jms.listener",
- "org.springframework.jms.listener.adapter");
+ "org.springframework.jms.listener.adapter")
+ .addImports(EnableJmsMessaging.class.getCanonicalName());
}
+ @Target(ElementType.TYPE)
+ @Documented
+ @Retention(RetentionPolicy.RUNTIME)
+ public static @interface EnableJmsMessaging {
+
+ }
+
}
diff --git a/spring-boot-dependencies/pom.xml b/spring-boot-dependencies/pom.xml
index 055617e518..53f98617bd 100644
--- a/spring-boot-dependencies/pom.xml
+++ b/spring-boot-dependencies/pom.xml
@@ -111,6 +111,11 @@
activemq-core
${activemq.version}
+
+ org.apache.activemq
+ activemq-pool
+ ${activemq.version}
+
org.apache.tomcat.embed
tomcat-embed-core