Rabbit Configuration Corrections

Fixes #564

- Correct an issue where if the `cloud` profile is enabled but no Connectors are available,
no `ConnectionFactory` will be created;
- Introduce a property named `spring.cloud.stream.overrideCloudConnectors` that allows
to suppress the use of Cloud connectors in the application and fall back to Spring Boot
configuration. This is provided so that specific binders can be created with arbitrary
connectivity parameters if needed.
- Add documentation.
This commit is contained in:
Marius Bogoevici
2016-06-06 14:54:43 -04:00
parent 9a65728cc6
commit f8e4df4711
2 changed files with 83 additions and 13 deletions

View File

@@ -20,11 +20,13 @@ import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.boot.actuate.health.RabbitHealthIndicator;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration;
import org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration;
import org.springframework.boot.autoconfigure.amqp.RabbitProperties;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.Cloud;
import org.springframework.cloud.CloudFactory;
import org.springframework.cloud.stream.binder.Binder;
@@ -41,11 +43,11 @@ import org.springframework.context.annotation.Profile;
* @author Glenn Renfro
* @author David Turanski
* @author Eric Bottard
* @author Marius Bogoevici
*/
@Configuration
@ConditionalOnMissingBean(Binder.class)
@Import(RabbitMessageChannelBinderConfiguration.class)
@AutoConfigureBefore({CloudAutoConfiguration.class, RabbitAutoConfiguration.class})
public class RabbitServiceAutoConfiguration {
@Bean
@@ -53,26 +55,83 @@ public class RabbitServiceAutoConfiguration {
return new RabbitHealthIndicator(rabbitTemplate);
}
/**
* Configuration to be used when the cloud profile is set.
*/
@Configuration
@Profile("cloud")
@ConditionalOnClass(Cloud.class)
protected static class CloudConfig {
protected static class CloudProfile {
@Bean
public Cloud cloud() {
return new CloudFactory().getCloud();
/**
* Configuration to be used when the cloud profile is set, and Cloud Connectors
* are found on the classpath.
*/
@Configuration
@ConditionalOnClass(Cloud.class)
protected static class CloudConnectors {
@Bean
public Cloud cloud() {
return new CloudFactory().getCloud();
}
/**
* Active only if {@code spring.cloud.stream.overrideCloudConnectors} is not
* set to {@code true}.
*/
@Configuration
@ConditionalOnProperty(value = "spring.cloud.stream.overrideCloudConnectors", havingValue = "false", matchIfMissing = true)
// Required to parse Rabbit properties which are passed to the binder for
// clustering. We need to enable it here explicitly as the default Rabbit
// configuration is not triggered.
@EnableConfigurationProperties(RabbitProperties.class)
protected static class UseCloudConnectors {
/**
* Creates a {@link ConnectionFactory} using the singleton service
* connector.
*
* @param cloud {@link Cloud} instance to be used for accessing services.
* @return the {@link ConnectionFactory} used by the binder.
*/
@Bean
ConnectionFactory rabbitConnectionFactory(Cloud cloud) {
return cloud.getSingletonServiceConnector(ConnectionFactory.class, null);
}
@Bean
@ConditionalOnMissingBean(RabbitTemplate.class)
RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
return new RabbitTemplate(connectionFactory);
}
}
/**
* Configuration to be used if
* {@code spring.cloud.stream.overrideCloudConnectors} is set to {@code true}.
* Defers to Spring Boot Autoconfiguration.
*/
@Configuration
@ConditionalOnProperty("spring.cloud.stream.overrideCloudConnectors")
@Import(RabbitAutoConfiguration.class)
protected static class OverrideCloudConnectors {
}
}
@Bean
@ConditionalOnMissingBean(ConnectionFactory.class)
ConnectionFactory rabbitConnectionFactory(Cloud cloud) {
return cloud.getSingletonServiceConnector(ConnectionFactory.class, null);
@Configuration
@ConditionalOnMissingClass("org.springframework.cloud.Cloud")
@Import(RabbitAutoConfiguration.class)
protected static class NoCloudConnectors {
}
}
/**
* Configuration to be used when the cloud profile is not set. Defer to Spring Boot
* autoconfiguration.
*/
@Configuration
@Profile("!cloud")
@Import(RabbitAutoConfiguration.class)
protected static class NoCloudConfig {
protected static class NoCloudProfile {
}
}

View File

@@ -720,6 +720,7 @@ spring.cloud.stream.bindings.input.binder=kafka
spring.cloud.stream.bindings.output.binder=rabbit
----
[[multiple-systems]]
=== Connecting to Multiple Systems
By default, binders share the application's Spring Boot auto-configuration, so that one instance of each binder found on the classpath will be created.
@@ -842,6 +843,16 @@ Default: empty (allowing any destination to be bound).
spring.cloud.stream.defaultBinder::
The default binder to use, if multiple binders are configured.
See <<multiple-binders,Multiple Binders on the Classpath>>.
+
Default: empty.
spring.cloud.stream.overrideCloudConnectors::
This property is only applicable when the `cloud` profile is active and Spring Cloud Connectors are provided with the application.
If the property is false (the default), the binder will detect a suitable bound service (e.g. a RabbitMQ service bound in Cloud Foundry for the RabbitMQ binder) and will use it for creating connections (usually via Spring Cloud Connectors).
When set to true, this property instructs binders to completely ignore the bound services and rely on Spring Boot properties (e.g. relying on the `spring.rabbitmq.*` properties provided in the environment for the RabbitMQ binder).
The typical usage of this property is to be nested in a customized environment <<multiple-systems, when connecting to multiple systems>>.
+
Default: false.
[[binding-properties]]
=== Binding Properties