Add JMS autoconfig support
* application.properties support for spring.jms and spring.activemq * more tests to verify ActiveMQConnectionFactory pooling * Groovy support and simple sample with activemq * Groovy detection mechanism is @EnableJmsMessaging annotation
This commit is contained in:
committed by
Dave Syer
parent
e16a0278ae
commit
fa6e6fde6c
@@ -31,6 +31,11 @@
|
||||
<artifactId>activemq-core</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.activemq</groupId>
|
||||
<artifactId>activemq-pool</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat.embed</groupId>
|
||||
<artifactId>tomcat-embed-core</artifactId>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -111,6 +111,11 @@
|
||||
<artifactId>activemq-core</artifactId>
|
||||
<version>${activemq.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.activemq</groupId>
|
||||
<artifactId>activemq-pool</artifactId>
|
||||
<version>${activemq.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat.embed</groupId>
|
||||
<artifactId>tomcat-embed-core</artifactId>
|
||||
|
||||
Reference in New Issue
Block a user