diff --git a/.gitignore b/.gitignore
index 4e580f3d8b..8c14632e59 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,4 +18,4 @@ _site/
manifest.yml
MANIFEST.MF
settings.xml
-
+activemq-data
diff --git a/spring-boot-autoconfigure/pom.xml b/spring-boot-autoconfigure/pom.xml
index 0d09b51cc7..fc45fad4fb 100644
--- a/spring-boot-autoconfigure/pom.xml
+++ b/spring-boot-autoconfigure/pom.xml
@@ -26,6 +26,11 @@
commons-dbcp
true
+
+ org.apache.activemq
+ activemq-core
+ true
+
org.apache.tomcat.embed
tomcat-embed-core
@@ -56,6 +61,11 @@
spring-jdbc
true
+
+ org.springframework
+ spring-jms
+ true
+
org.springframework
spring-orm
@@ -126,6 +136,10 @@
reactor-spring
true
+
+ org.apache.geronimo.specs
+ geronimo-jms_1.1_spec
+
${project.groupId}
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
new file mode 100644
index 0000000000..bb08f175b2
--- /dev/null
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsTemplateAutoConfiguration.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2012-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.boot.autoconfigure.jms;
+
+import javax.jms.ConnectionFactory;
+
+import org.apache.activemq.ActiveMQConnectionFactory;
+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.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.jms.core.JmsTemplate;
+
+/**
+ * {@link EnableAutoConfiguration Auto-configuration} for {@link JmsTemplate}.
+ *
+ * @author Greg Turnquist
+ */
+@Configuration
+@ConditionalOnClass(JmsTemplate.class)
+public class JmsTemplateAutoConfiguration {
+
+ @Configuration
+ @ConditionalOnMissingBean(JmsTemplate.class)
+ protected static class JmsTemplateCreator {
+
+ @Autowired
+ ConnectionFactory connectionFactory;
+
+ @Bean
+ public JmsTemplate jmsTemplate() {
+ JmsTemplate jmsTemplate = new JmsTemplate(connectionFactory);
+ jmsTemplate.setPubSubDomain(true);
+ return jmsTemplate;
+ }
+
+ }
+
+ @Configuration
+ @ConditionalOnClass(ActiveMQConnectionFactory.class)
+ @ConditionalOnMissingBean(ConnectionFactory.class)
+ protected static class ActiveMQConnectionFactoryCreator {
+ @Bean
+ ConnectionFactory connectionFactory() {
+ return new ActiveMQConnectionFactory("vm://localhost");
+ }
+ }
+
+}
diff --git a/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories b/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories
index 7123ea0f52..f150d12c56 100644
--- a/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories
+++ b/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories
@@ -8,6 +8,7 @@ org.springframework.boot.autoconfigure.data.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.MongoRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
+org.springframework.boot.autoconfigure.jms.JmsTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.reactor.ReactorAutoConfiguration,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
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
new file mode 100644
index 0000000000..840761d873
--- /dev/null
+++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/JmsTemplateAutoConfigurationTests.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2012-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.boot.autoconfigure.jms;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import javax.jms.ConnectionFactory;
+
+import org.apache.activemq.ActiveMQConnectionFactory;
+import org.junit.Test;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.config.BeanPostProcessor;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.jms.core.JmsTemplate;
+
+/**
+ * Tests for {@link JmsTemplateAutoConfiguration}.
+ *
+ * @author Greg Turnquist
+ */
+public class JmsTemplateAutoConfigurationTests {
+
+ private AnnotationConfigApplicationContext context;
+
+ @Test
+ public void testDefaultJmsTemplate() {
+ this.context = new AnnotationConfigApplicationContext();
+ this.context
+ .register(TestConfiguration.class, JmsTemplateAutoConfiguration.class);
+ 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);
+ }
+
+ @Configuration
+ protected static class TestConfiguration {
+ }
+
+ @Test
+ public void testConnectionFactoryBackoff() {
+ this.context = new AnnotationConfigApplicationContext();
+ this.context.register(TestConfiguration2.class,
+ JmsTemplateAutoConfiguration.class);
+ this.context.refresh();
+ assertEquals("foobar", this.context.getBean(ActiveMQConnectionFactory.class)
+ .getBrokerURL());
+ }
+
+ @Configuration
+ protected static class TestConfiguration2 {
+ @Bean
+ ConnectionFactory connectionFactory() {
+ return new ActiveMQConnectionFactory() {
+ {
+ setBrokerURL("foobar");
+ }
+ };
+ }
+ }
+
+ @Test
+ public void testJmsTemplateBackoff() {
+ this.context = new AnnotationConfigApplicationContext();
+ this.context.register(TestConfiguration3.class,
+ JmsTemplateAutoConfiguration.class);
+ this.context.refresh();
+ JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class);
+ assertEquals(999, jmsTemplate.getPriority());
+ }
+
+ @Configuration
+ protected static class TestConfiguration3 {
+ @Bean
+ JmsTemplate jmsTemplate(ConnectionFactory connectionFactory) {
+ JmsTemplate jmsTemplate = new JmsTemplate(connectionFactory);
+ jmsTemplate.setPriority(999);
+ return jmsTemplate;
+ }
+
+ }
+
+ @Test
+ public void testJmsTemplateBackoffEverything() {
+ this.context = new AnnotationConfigApplicationContext();
+ this.context.register(TestConfiguration2.class, TestConfiguration3.class,
+ JmsTemplateAutoConfiguration.class);
+ this.context.refresh();
+ JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class);
+ assertEquals(999, jmsTemplate.getPriority());
+ assertEquals("foobar", this.context.getBean(ActiveMQConnectionFactory.class)
+ .getBrokerURL());
+ }
+
+ @Test
+ public void testPubSubEnabledByDefault() {
+ this.context = new AnnotationConfigApplicationContext();
+ this.context
+ .register(TestConfiguration.class, JmsTemplateAutoConfiguration.class);
+ this.context.refresh();
+ JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class);
+ assertTrue(jmsTemplate.isPubSubDomain());
+ }
+
+ @Test
+ public void testJmsTemplatePostProcessedSoThatPubSubIsFalse() {
+ this.context = new AnnotationConfigApplicationContext();
+ this.context.register(TestConfiguration4.class,
+ JmsTemplateAutoConfiguration.class);
+ this.context.refresh();
+ JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class);
+ assertFalse(jmsTemplate.isPubSubDomain());
+ }
+
+ @Configuration
+ protected static class TestConfiguration4 implements BeanPostProcessor {
+ @Override
+ public Object postProcessAfterInitialization(Object bean, String beanName)
+ throws BeansException {
+ if (bean.getClass().isAssignableFrom(JmsTemplate.class)) {
+ JmsTemplate jmsTemplate = (JmsTemplate) bean;
+ jmsTemplate.setPubSubDomain(false);
+ }
+ return bean;
+ }
+
+ @Override
+ public Object postProcessBeforeInitialization(Object bean, String beanName)
+ throws BeansException {
+ return bean;
+ }
+ }
+
+}
diff --git a/spring-boot-cli/samples/jms.groovy b/spring-boot-cli/samples/jms.groovy
new file mode 100644
index 0000000000..54454fa1e8
--- /dev/null
+++ b/spring-boot-cli/samples/jms.groovy
@@ -0,0 +1,48 @@
+package org.test
+
+@Grab("org.apache.activemq:activemq-all:5.2.0")
+
+import java.util.concurrent.CountDownLatch
+
+@Configuration
+@Log
+class JmsExample implements CommandLineRunner {
+
+ private CountDownLatch latch = new CountDownLatch(1)
+
+ @Autowired
+ JmsTemplate jmsTemplate
+
+ @Bean
+ DefaultMessageListenerContainer jmsListener(ConnectionFactory connectionFactory) {
+ new DefaultMessageListenerContainer([
+ connectionFactory: connectionFactory,
+ destinationName: "spring-boot",
+ pubSubDomain: true,
+ messageListener: new MessageListenerAdapter(new Receiver(latch:latch)) {{
+ defaultListenerMethod = "receive"
+ }}
+ ])
+ }
+
+ void run(String... args) {
+ def messageCreator = { session ->
+ 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()
+ }
+
+}
+
+@Log
+class Receiver {
+ CountDownLatch latch
+
+ def receive(String message) {
+ log.info "Received ${message}"
+ latch.countDown()
+ }
+}
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
new file mode 100644
index 0000000000..5c6d47454a
--- /dev/null
+++ b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/autoconfigure/JmsCompilerAutoConfiguration.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2012-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.boot.cli.compiler.autoconfigure;
+
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.control.CompilationFailedException;
+import org.codehaus.groovy.control.customizers.ImportCustomizer;
+import org.springframework.boot.cli.compiler.AstUtils;
+import org.springframework.boot.cli.compiler.CompilerAutoConfiguration;
+import org.springframework.boot.cli.compiler.DependencyCustomizer;
+
+/**
+ * {@link CompilerAutoConfiguration} for Spring JMS.
+ *
+ * @author Greg Turnquist
+ */
+public class JmsCompilerAutoConfiguration extends CompilerAutoConfiguration {
+
+ @Override
+ public boolean matches(ClassNode classNode) {
+ return AstUtils.hasAtLeastOneFieldOrMethod(classNode, "JmsTemplate",
+ "DefaultMessageListenerContainer", "SimpleMessageListenerContainer");
+ }
+
+ @Override
+ public void applyDependencies(DependencyCustomizer dependencies)
+ throws CompilationFailedException {
+ dependencies.add("org.springframework", "spring-jms",
+ dependencies.getProperty("spring.version")).add(
+ "org.apache.geronimo.specs", "geronimo-jms_1.1_spec", "1.1");
+
+ }
+
+ @Override
+ public void applyImports(ImportCustomizer imports) throws CompilationFailedException {
+ imports.addStarImports("javax.jms", "org.springframework.jms.core",
+ "org.springframework.jms.listener",
+ "org.springframework.jms.listener.adapter");
+ }
+
+}
diff --git a/spring-boot-cli/src/main/resources/META-INF/services/org.springframework.boot.cli.compiler.CompilerAutoConfiguration b/spring-boot-cli/src/main/resources/META-INF/services/org.springframework.boot.cli.compiler.CompilerAutoConfiguration
index ac2b474d5b..0f28cef01e 100644
--- a/spring-boot-cli/src/main/resources/META-INF/services/org.springframework.boot.cli.compiler.CompilerAutoConfiguration
+++ b/spring-boot-cli/src/main/resources/META-INF/services/org.springframework.boot.cli.compiler.CompilerAutoConfiguration
@@ -3,6 +3,7 @@ org.springframework.boot.cli.compiler.autoconfigure.SpringMvcCompilerAutoConfigu
org.springframework.boot.cli.compiler.autoconfigure.SpringBatchCompilerAutoConfiguration
org.springframework.boot.cli.compiler.autoconfigure.ReactorCompilerAutoConfiguration
org.springframework.boot.cli.compiler.autoconfigure.JdbcCompilerAutoConfiguration
+org.springframework.boot.cli.compiler.autoconfigure.JmsCompilerAutoConfiguration
org.springframework.boot.cli.compiler.autoconfigure.TransactionManagementCompilerAutoConfiguration
org.springframework.boot.cli.compiler.autoconfigure.SpringIntegrationCompilerAutoConfiguration
org.springframework.boot.cli.compiler.autoconfigure.SpringSecurityCompilerAutoConfiguration
diff --git a/spring-boot-cli/src/test/java/org/springframework/boot/cli/SampleIntegrationTests.java b/spring-boot-cli/src/test/java/org/springframework/boot/cli/SampleIntegrationTests.java
index f0fae17ea7..28d38b66fc 100644
--- a/spring-boot-cli/src/test/java/org/springframework/boot/cli/SampleIntegrationTests.java
+++ b/spring-boot-cli/src/test/java/org/springframework/boot/cli/SampleIntegrationTests.java
@@ -16,6 +16,10 @@
package org.springframework.boot.cli;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
import java.net.URL;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
@@ -32,13 +36,11 @@ import org.springframework.boot.OutputCapture;
import org.springframework.boot.cli.command.CleanCommand;
import org.springframework.boot.cli.command.RunCommand;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
/**
* Integration tests to exercise the samples.
*
* @author Dave Syer
+ * @author Greg Turnquist
*/
public class SampleIntegrationTests {
@@ -185,4 +187,13 @@ public class SampleIntegrationTests {
assertTrue("Wrong output: " + output, output.contains("Foo count="));
}
+ @Test
+ public void jmsSample() throws Exception {
+ start("samples/app.xml", "samples/jms.groovy");
+ String output = this.outputCapture.getOutputAndRelease();
+ assertTrue("Wrong output: " + output,
+ output.contains("Received Greetings from Spring Boot via ActiveMQ"));
+ FileUtil.forceDelete(new File("activemq-data")); // cleanup ActiveMQ cruft
+ }
+
}
diff --git a/spring-boot-cli/src/test/resources/logback.xml b/spring-boot-cli/src/test/resources/logback.xml
index ab0a65c9a9..29a2b9b369 100644
--- a/spring-boot-cli/src/test/resources/logback.xml
+++ b/spring-boot-cli/src/test/resources/logback.xml
@@ -1,5 +1,5 @@
-
+
diff --git a/spring-boot-dependencies/pom.xml b/spring-boot-dependencies/pom.xml
index eff1bf0e0f..3c6e4a53f8 100644
--- a/spring-boot-dependencies/pom.xml
+++ b/spring-boot-dependencies/pom.xml
@@ -7,6 +7,7 @@
0.5.0.BUILD-SNAPSHOT
pom
+ 5.7.0
1.7.3
1.4
3.1
@@ -105,6 +106,11 @@
thymeleaf-layout-dialect
${thymeleaf-layout-dialect.version}
+
+ org.apache.activemq
+ activemq-core
+ ${activemq.version}
+
org.apache.tomcat.embed
tomcat-embed-core
@@ -429,6 +435,11 @@
snakeyaml
${snakeyaml.version}
+
+ org.apache.geronimo.specs
+ geronimo-jms_1.1_spec
+ 1.1
+