diff --git a/spring-cloud-stream-binders/spring-cloud-stream-binder-rabbit/src/main/java/org/springframework/cloud/stream/binder/rabbit/config/RabbitServiceAutoConfiguration.java b/spring-cloud-stream-binders/spring-cloud-stream-binder-rabbit/src/main/java/org/springframework/cloud/stream/binder/rabbit/config/RabbitServiceAutoConfiguration.java index c69798c57..34a8ece22 100644 --- a/spring-cloud-stream-binders/spring-cloud-stream-binder-rabbit/src/main/java/org/springframework/cloud/stream/binder/rabbit/config/RabbitServiceAutoConfiguration.java +++ b/spring-cloud-stream-binders/spring-cloud-stream-binder-rabbit/src/main/java/org/springframework/cloud/stream/binder/rabbit/config/RabbitServiceAutoConfiguration.java @@ -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 { } } diff --git a/spring-cloud-stream-docs/src/main/asciidoc/spring-cloud-stream-overview.adoc b/spring-cloud-stream-docs/src/main/asciidoc/spring-cloud-stream-overview.adoc index 9898d1cfd..9514bea15 100644 --- a/spring-cloud-stream-docs/src/main/asciidoc/spring-cloud-stream-overview.adoc +++ b/spring-cloud-stream-docs/src/main/asciidoc/spring-cloud-stream-overview.adoc @@ -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 <>. ++ +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 <>. ++ +Default: false. [[binding-properties]] === Binding Properties