Expose additional RabbitMQ settings
Allow SSL to be configured via standard configuration as well as the requestedHeartbeat. Switch to RabbitConnectionFactoryBean. Closes gh-2655, gh-2676
This commit is contained in:
parent
ab55331863
commit
e3a124d0f9
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2014 the original author or authors.
|
||||
* Copyright 2012-2015 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.
|
||||
|
|
@ -16,9 +16,13 @@
|
|||
|
||||
package org.springframework.boot.autoconfigure.amqp;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.springframework.amqp.core.AmqpAdmin;
|
||||
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
|
||||
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
|
||||
import org.springframework.amqp.rabbit.connection.RabbitConnectionFactoryBean;
|
||||
import org.springframework.amqp.rabbit.core.RabbitAdmin;
|
||||
import org.springframework.amqp.rabbit.core.RabbitMessagingTemplate;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
|
|
@ -31,6 +35,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
|
|||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.core.io.ByteArrayResource;
|
||||
|
||||
import com.rabbitmq.client.Channel;
|
||||
|
||||
|
|
@ -72,6 +77,7 @@ import com.rabbitmq.client.Channel;
|
|||
* </ul>
|
||||
* @author Greg Turnquist
|
||||
* @author Josh Long
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass({ RabbitTemplate.class, Channel.class })
|
||||
|
|
@ -100,10 +106,8 @@ public class RabbitAutoConfiguration {
|
|||
protected static class RabbitConnectionFactoryCreator {
|
||||
|
||||
@Bean
|
||||
public ConnectionFactory rabbitConnectionFactory(RabbitProperties config) {
|
||||
CachingConnectionFactory factory = new CachingConnectionFactory();
|
||||
String addresses = config.getAddresses();
|
||||
factory.setAddresses(addresses);
|
||||
public ConnectionFactory rabbitConnectionFactory(RabbitProperties config) throws Exception {
|
||||
RabbitConnectionFactoryBean factory = new RabbitConnectionFactoryBean();
|
||||
if (config.getHost() != null) {
|
||||
factory.setHost(config.getHost());
|
||||
factory.setPort(config.getPort());
|
||||
|
|
@ -117,7 +121,24 @@ public class RabbitAutoConfiguration {
|
|||
if (config.getVirtualHost() != null) {
|
||||
factory.setVirtualHost(config.getVirtualHost());
|
||||
}
|
||||
return factory;
|
||||
if (config.getRequestedHeartbeat() != null) {
|
||||
factory.setRequestedHeartbeat(config.getRequestedHeartbeat());
|
||||
}
|
||||
RabbitProperties.Ssl ssl = config.getSsl();
|
||||
if (ssl.isEnabled()) {
|
||||
factory.setUseSSL(true);
|
||||
if (ssl.getKeyStore() != null || ssl.getTrustStore() != null) {
|
||||
Properties properties = ssl.createSslProperties();
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
properties.store(outputStream, "SSL config");
|
||||
factory.setSslPropertiesLocation(
|
||||
new ByteArrayResource(outputStream.toByteArray()));
|
||||
}
|
||||
}
|
||||
factory.afterPropertiesSet();
|
||||
CachingConnectionFactory connectionFactory = new CachingConnectionFactory(factory.getObject());
|
||||
connectionFactory.setAddresses(config.getAddresses());
|
||||
return connectionFactory;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2014 the original author or authors.
|
||||
* Copyright 2012-2015 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.
|
||||
|
|
@ -17,6 +17,7 @@
|
|||
package org.springframework.boot.autoconfigure.amqp;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
|
@ -27,6 +28,7 @@ import org.springframework.util.StringUtils;
|
|||
*
|
||||
* @author Greg Turnquist
|
||||
* @author Dave Syer
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "spring.rabbitmq")
|
||||
public class RabbitProperties {
|
||||
|
|
@ -51,6 +53,11 @@ public class RabbitProperties {
|
|||
*/
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* SSL configuration.
|
||||
*/
|
||||
private final Ssl ssl = new Ssl();
|
||||
|
||||
/**
|
||||
* Virtual host to use when connecting to the broker.
|
||||
*/
|
||||
|
|
@ -61,6 +68,12 @@ public class RabbitProperties {
|
|||
*/
|
||||
private String addresses;
|
||||
|
||||
/**
|
||||
* Requested heartbeat timeout, in seconds; zero for none.
|
||||
*/
|
||||
private Integer requestedHeartbeat;
|
||||
|
||||
|
||||
public String getHost() {
|
||||
if (this.addresses == null) {
|
||||
return this.host;
|
||||
|
|
@ -147,6 +160,10 @@ public class RabbitProperties {
|
|||
this.password = password;
|
||||
}
|
||||
|
||||
public Ssl getSsl() {
|
||||
return ssl;
|
||||
}
|
||||
|
||||
public String getVirtualHost() {
|
||||
return this.virtualHost;
|
||||
}
|
||||
|
|
@ -155,4 +172,102 @@ public class RabbitProperties {
|
|||
this.virtualHost = ("".equals(virtualHost) ? "/" : virtualHost);
|
||||
}
|
||||
|
||||
public Integer getRequestedHeartbeat() {
|
||||
return requestedHeartbeat;
|
||||
}
|
||||
|
||||
public void setRequestedHeartbeat(Integer requestedHeartbeat) {
|
||||
this.requestedHeartbeat = requestedHeartbeat;
|
||||
}
|
||||
|
||||
public static class Ssl {
|
||||
|
||||
/**
|
||||
* Enable SSL support.
|
||||
*/
|
||||
private boolean enabled;
|
||||
|
||||
/**
|
||||
* Path to the key store that holds the SSL certificate.
|
||||
*/
|
||||
private String keyStore;
|
||||
|
||||
/**
|
||||
* Password used to access the key store.
|
||||
*/
|
||||
private String keyStorePassword;
|
||||
|
||||
/**
|
||||
* Trust store that holds SSL certificates.
|
||||
*/
|
||||
private String trustStore;
|
||||
|
||||
/**
|
||||
* Password used to access the trust store.
|
||||
*/
|
||||
private String trustStorePassword;
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public String getKeyStore() {
|
||||
return keyStore;
|
||||
}
|
||||
|
||||
public void setKeyStore(String keyStore) {
|
||||
this.keyStore = keyStore;
|
||||
}
|
||||
|
||||
public String getKeyStorePassword() {
|
||||
return keyStorePassword;
|
||||
}
|
||||
|
||||
public void setKeyStorePassword(String keyStorePassword) {
|
||||
this.keyStorePassword = keyStorePassword;
|
||||
}
|
||||
|
||||
public String getTrustStore() {
|
||||
return trustStore;
|
||||
}
|
||||
|
||||
public void setTrustStore(String trustStore) {
|
||||
this.trustStore = trustStore;
|
||||
}
|
||||
|
||||
public String getTrustStorePassword() {
|
||||
return trustStorePassword;
|
||||
}
|
||||
|
||||
public void setTrustStorePassword(String trustStorePassword) {
|
||||
this.trustStorePassword = trustStorePassword;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the ssl configuration as expected by the
|
||||
* {@link org.springframework.amqp.rabbit.connection.RabbitConnectionFactoryBean RabbitConnectionFactoryBean}.
|
||||
* @return the ssl configuration
|
||||
*/
|
||||
public Properties createSslProperties() {
|
||||
Properties properties = new Properties();
|
||||
if (getKeyStore() != null) {
|
||||
properties.put("keyStore", getKeyStore());
|
||||
}
|
||||
if (getKeyStorePassword() != null) {
|
||||
properties.put("keyStore.passPhrase", getKeyStorePassword());
|
||||
}
|
||||
if (getTrustStore() != null) {
|
||||
properties.put("trustStore", getTrustStore());
|
||||
}
|
||||
if (getTrustStorePassword() != null) {
|
||||
properties.put("trustStore.passPhrase", getTrustStorePassword());
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2014 the original author or authors.
|
||||
* Copyright 2012-2015 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.
|
||||
|
|
@ -16,6 +16,9 @@
|
|||
|
||||
package org.springframework.boot.autoconfigure.amqp;
|
||||
|
||||
import javax.net.SocketFactory;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
|
@ -31,6 +34,7 @@ import org.springframework.amqp.rabbit.core.RabbitMessagingTemplate;
|
|||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.amqp.rabbit.listener.RabbitListenerContainerFactory;
|
||||
import org.springframework.amqp.support.converter.MessageConverter;
|
||||
import org.springframework.beans.DirectFieldAccessor;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.boot.test.EnvironmentTestUtils;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
|
|
@ -47,6 +51,7 @@ import static org.mockito.Mockito.verify;
|
|||
* Tests for {@link RabbitAutoConfiguration}.
|
||||
*
|
||||
* @author Greg Turnquist
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public class RabbitAutoConfigurationTests {
|
||||
|
||||
|
|
@ -188,6 +193,46 @@ public class RabbitAutoConfigurationTests {
|
|||
ctx.getBean(RabbitListenerConfigUtils.RABBIT_LISTENER_ENDPOINT_REGISTRY_BEAN_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customizeRequestedHeartBeat() {
|
||||
load(TestConfiguration.class, "spring.rabbitmq.requestedHeartbeat:20");
|
||||
com.rabbitmq.client.ConnectionFactory rabbitConnectionFactory = getTargetConnectionFactory();
|
||||
assertEquals(20, rabbitConnectionFactory.getRequestedHeartbeat());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noSslByDefault() {
|
||||
load(TestConfiguration.class);
|
||||
com.rabbitmq.client.ConnectionFactory rabbitConnectionFactory = getTargetConnectionFactory();
|
||||
assertEquals("Must use default SocketFactory", SocketFactory.getDefault(),
|
||||
rabbitConnectionFactory.getSocketFactory());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void enableSsl() {
|
||||
load(TestConfiguration.class, "spring.rabbitmq.ssl.enabled:true");
|
||||
com.rabbitmq.client.ConnectionFactory rabbitConnectionFactory = getTargetConnectionFactory();
|
||||
assertTrue("SocketFactory must use SSL", rabbitConnectionFactory.getSocketFactory() instanceof SSLSocketFactory);
|
||||
}
|
||||
|
||||
@Test // Make sure that we at least attempt to load the store
|
||||
public void enableSslWithExtraConfig() {
|
||||
thrown.expectMessage("foo");
|
||||
thrown.expectMessage("does not exist");
|
||||
load(TestConfiguration.class, "spring.rabbitmq.ssl.enabled:true",
|
||||
"spring.rabbitmq.ssl.keyStore=foo",
|
||||
"spring.rabbitmq.ssl.keyStorePassword=secret",
|
||||
"spring.rabbitmq.ssl.trustStore=bar",
|
||||
"spring.rabbitmq.ssl.trustStorePassword=secret");
|
||||
}
|
||||
|
||||
private com.rabbitmq.client.ConnectionFactory getTargetConnectionFactory() {
|
||||
CachingConnectionFactory connectionFactory = this.context
|
||||
.getBean(CachingConnectionFactory.class);
|
||||
return (com.rabbitmq.client.ConnectionFactory)
|
||||
new DirectFieldAccessor(connectionFactory).getPropertyValue("rabbitConnectionFactory");
|
||||
}
|
||||
|
||||
private void load(Class<?> config, String... environment) {
|
||||
this.context = doLoad(new Class<?>[] { config }, environment);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -428,13 +428,19 @@ content into your application; rather pick only the properties that you need.
|
|||
spring.jmx.enabled=true # Expose MBeans from Spring
|
||||
|
||||
# RABBIT ({sc-spring-boot-autoconfigure}/amqp/RabbitProperties.{sc-ext}[RabbitProperties])
|
||||
spring.rabbitmq.addresses= # connection addresses (e.g. myhost:9999,otherhost:1111)
|
||||
spring.rabbitmq.dynamic=true # create an AmqpAdmin bean
|
||||
spring.rabbitmq.host= # connection host
|
||||
spring.rabbitmq.port= # connection port
|
||||
spring.rabbitmq.addresses= # connection addresses (e.g. myhost:9999,otherhost:1111)
|
||||
spring.rabbitmq.username= # login user
|
||||
spring.rabbitmq.password= # login password
|
||||
spring.rabbitmq.virtual-host=
|
||||
spring.rabbitmq.dynamic=
|
||||
spring.rabbitmq.requested-heartbeat= # requested heartbeat timeout, in seconds; zero for none
|
||||
spring.rabbitmq.ssl.enabled=false # enable SSL support
|
||||
spring.rabbitmq.ssl.key-store= # path to the key store that holds the SSL certificate
|
||||
spring.rabbitmq.ssl.key-store-password= # password used to access the key store
|
||||
spring.rabbitmq.ssl.trust-store= # trust store that holds SSL certificates
|
||||
spring.rabbitmq.ssl.trust-store-password= # password used to access the trust store
|
||||
spring.rabbitmq.username= # login user
|
||||
spring.rabbitmq.virtual-host= # virtual host to use when connecting to the broker
|
||||
|
||||
# REDIS ({sc-spring-boot-autoconfigure}/redis/RedisProperties.{sc-ext}[RedisProperties])
|
||||
spring.redis.database= # database name
|
||||
|
|
|
|||
Loading…
Reference in New Issue