diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
index cdd2a9295b1d..594f11918494 100644
--- a/.idea/codeStyles/Project.xml
+++ b/.idea/codeStyles/Project.xml
@@ -8,19 +8,6 @@
-
@@ -121,4 +108,4 @@
-
+
\ No newline at end of file
diff --git a/documentation/spring-boot-docs/build.gradle b/documentation/spring-boot-docs/build.gradle
index b4a3d44067d9..41144382e66e 100644
--- a/documentation/spring-boot-docs/build.gradle
+++ b/documentation/spring-boot-docs/build.gradle
@@ -126,6 +126,7 @@ dependencies {
implementation(project(path: ":module:spring-boot-micrometer-metrics"))
implementation(project(path: ":module:spring-boot-persistence"))
implementation(project(path: ":module:spring-boot-r2dbc"))
+ implementation(project(path: ":module:spring-boot-rabbitmq"))
implementation(project(path: ":module:spring-boot-restdocs"))
implementation(project(path: ":module:spring-boot-reactor-netty"))
implementation(project(path: ":module:spring-boot-restclient"))
diff --git a/documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/actuator/endpoints.adoc b/documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/actuator/endpoints.adoc
index 31f7874b26e4..1e0f23163c74 100644
--- a/documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/actuator/endpoints.adoc
+++ b/documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/actuator/endpoints.adoc
@@ -670,7 +670,7 @@ with the `key` listed in the following table:
| Always responds with `UP`.
| `rabbit`
-| javadoc:org.springframework.boot.amqp.health.RabbitHealthIndicator[]
+| javadoc:org.springframework.boot.rabbitmq.health.RabbitHealthIndicator[]
| Checks that a Rabbit server is up.
| `redis`
diff --git a/documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/features/dev-services.adoc b/documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/features/dev-services.adoc
index fbaab365f52f..a46be64c3d93 100644
--- a/documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/features/dev-services.adoc
+++ b/documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/features/dev-services.adoc
@@ -126,6 +126,9 @@ The following service connections are currently supported:
| Containers named "clickhouse/clickhouse-server", "gvenzl/oracle-free", "gvenzl/oracle-xe", "mariadb", "mssql/server", "mysql", or "postgres"
| javadoc:org.springframework.boot.amqp.autoconfigure.RabbitConnectionDetails[]
+| Containers named "rabbitmq"
+
+| javadoc:org.springframework.boot.rabbitmq.autoconfigure.RabbitConnectionDetails[]
| Containers named "rabbitmq" with container port 5672 mapped
| javadoc:org.springframework.boot.amqp.autoconfigure.RabbitStreamConnectionDetails[]
diff --git a/documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/messaging/amqp.adoc b/documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/messaging/amqp.adoc
index 2f928840c73e..196f10af8c1d 100644
--- a/documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/messaging/amqp.adoc
+++ b/documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/messaging/amqp.adoc
@@ -38,12 +38,12 @@ spring:
NOTE: When specifying addresses that way, the `host` and `port` properties are ignored.
If the address uses the `amqps` protocol, SSL support is enabled automatically.
-See javadoc:org.springframework.boot.amqp.autoconfigure.RabbitProperties[] for more of the supported property-based configuration options.
-To configure lower-level details of the RabbitMQ javadoc:com.rabbitmq.client.ConnectionFactory[] that is used by Spring AMQP, define a javadoc:org.springframework.boot.amqp.autoconfigure.ConnectionFactoryCustomizer[] bean.
+See javadoc:org.springframework.boot.rabbitmq.autoconfigure.RabbitProperties[] for more of the supported property-based configuration options.
+To configure lower-level details of the RabbitMQ javadoc:com.rabbitmq.client.ConnectionFactory[] that is used by Spring AMQP, define a javadoc:org.springframework.boot.rabbitmq.autoconfigure.ConnectionFactoryCustomizer[] bean.
If a javadoc:org.springframework.amqp.rabbit.connection.ConnectionNameStrategy[] bean exists in the context, it will be automatically used to name connections created by the auto-configured javadoc:org.springframework.amqp.rabbit.connection.CachingConnectionFactory[].
-To make an application-wide, additive customization to the javadoc:org.springframework.amqp.rabbit.core.RabbitTemplate[], use a javadoc:org.springframework.boot.amqp.autoconfigure.RabbitTemplateCustomizer[] bean.
+To make an application-wide, additive customization to the javadoc:org.springframework.amqp.rabbit.core.RabbitTemplate[], use a javadoc:org.springframework.boot.rabbitmq.autoconfigure.RabbitTemplateCustomizer[] bean.
TIP: See https://spring.io/blog/2010/06/14/understanding-amqp-the-protocol-used-by-rabbitmq/[Understanding AMQP, the protocol used by RabbitMQ] for more details.
@@ -74,9 +74,9 @@ spring:
----
Retries are disabled by default.
-You can also customize the javadoc:org.springframework.core.retry.RetryTemplate[] programmatically by declaring a javadoc:org.springframework.boot.amqp.autoconfigure.RabbitTemplateRetrySettingsCustomizer[] bean.
+You can also customize the javadoc:org.springframework.core.retry.RetryTemplate[] programmatically by declaring a javadoc:org.springframework.boot.rabbitmq.autoconfigure.RabbitTemplateRetrySettingsCustomizer[] bean.
-If you need to create more javadoc:org.springframework.amqp.rabbit.core.RabbitTemplate[] instances or if you want to override the default, Spring Boot provides a javadoc:org.springframework.boot.amqp.autoconfigure.RabbitTemplateConfigurer[] bean that you can use to initialize a javadoc:org.springframework.amqp.rabbit.core.RabbitTemplate[] with the same settings as the factories used by the auto-configuration.
+If you need to create more javadoc:org.springframework.amqp.rabbit.core.RabbitTemplate[] instances or if you want to override the default, Spring Boot provides a javadoc:org.springframework.boot.rabbitmq.autoconfigure.RabbitTemplateConfigurer[] bean that you can use to initialize a javadoc:org.springframework.amqp.rabbit.core.RabbitTemplate[] with the same settings as the factories used by the auto-configuration.
If there's a bean of type javadoc:org.springframework.amqp.rabbit.support.micrometer.RabbitTemplateObservationConvention[] in the context, it will automatically be configured on the javadoc:org.springframework.amqp.rabbit.core.RabbitTemplate[].
@@ -97,7 +97,7 @@ spring:
If a javadoc:org.springframework.amqp.support.converter.MessageConverter[], javadoc:org.springframework.rabbit.stream.support.converter.StreamMessageConverter[], javadoc:org.springframework.rabbit.stream.producer.ProducerCustomizer[] or javadoc:org.springframework.rabbit.stream.micrometer.RabbitStreamTemplateObservationConvention[] bean is defined, it is associated automatically to the auto-configured javadoc:org.springframework.rabbit.stream.producer.RabbitStreamTemplate[].
-If you need to create more javadoc:org.springframework.rabbit.stream.producer.RabbitStreamTemplate[] instances or if you want to override the default, Spring Boot provides a javadoc:org.springframework.boot.amqp.autoconfigure.RabbitStreamTemplateConfigurer[] bean that you can use to initialize a javadoc:org.springframework.rabbit.stream.producer.RabbitStreamTemplate[] with the same settings as the factories used by the auto-configuration.
+If you need to create more javadoc:org.springframework.rabbit.stream.producer.RabbitStreamTemplate[] instances or if you want to override the default, Spring Boot provides a javadoc:org.springframework.boot.rabbitmq.autoconfigure.RabbitStreamTemplateConfigurer[] bean that you can use to initialize a javadoc:org.springframework.rabbit.stream.producer.RabbitStreamTemplate[] with the same settings as the factories used by the auto-configuration.
@@ -114,7 +114,7 @@ include-code::MyBean[]
TIP: See javadoc:org.springframework.amqp.rabbit.annotation.EnableRabbit[format=annotation] for more details.
-If you need to create more javadoc:org.springframework.amqp.rabbit.listener.RabbitListenerContainerFactory[] instances or if you want to override the default, Spring Boot provides a javadoc:org.springframework.boot.amqp.autoconfigure.SimpleRabbitListenerContainerFactoryConfigurer[] and a javadoc:org.springframework.boot.amqp.autoconfigure.DirectRabbitListenerContainerFactoryConfigurer[] that you can use to initialize a javadoc:org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory[] and a javadoc:org.springframework.amqp.rabbit.config.DirectRabbitListenerContainerFactory[] with the same settings as the factories used by the auto-configuration.
+If you need to create more javadoc:org.springframework.amqp.rabbit.listener.RabbitListenerContainerFactory[] instances or if you want to override the default, Spring Boot provides a javadoc:org.springframework.boot.rabbitmq.autoconfigure.SimpleRabbitListenerContainerFactoryConfigurer[] and a javadoc:org.springframework.boot.rabbitmq.autoconfigure.DirectRabbitListenerContainerFactoryConfigurer[] that you can use to initialize a javadoc:org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory[] and a javadoc:org.springframework.amqp.rabbit.config.DirectRabbitListenerContainerFactory[] with the same settings as the factories used by the auto-configuration.
TIP: It does not matter which container type you chose.
Those two beans are exposed by the auto-configuration.
@@ -131,7 +131,7 @@ You can enable retries to handle situations where your listener throws an except
By default, javadoc:org.springframework.amqp.rabbit.retry.RejectAndDontRequeueRecoverer[] is used, but you can define a javadoc:org.springframework.amqp.rabbit.retry.MessageRecoverer[] of your own.
When retries are exhausted, the message is rejected and either dropped or routed to a dead-letter exchange if the broker is configured to do so.
By default, retries are disabled.
-You can also customize the javadoc:org.springframework.core.retry.RetryPolicy[] programmatically by declaring a javadoc:org.springframework.boot.amqp.autoconfigure.RabbitListenerRetrySettingsCustomizer[] bean.
+You can also customize the javadoc:org.springframework.core.retry.RetryPolicy[] programmatically by declaring a javadoc:org.springframework.boot.rabbitmq.autoconfigure.RabbitListenerRetrySettingsCustomizer[] bean.
IMPORTANT: By default, if retries are disabled and the listener throws an exception, the delivery is retried indefinitely.
You can modify this behavior in two ways: Set the `defaultRequeueRejected` property to `false` so that zero re-deliveries are attempted or throw an javadoc:org.springframework.amqp.AmqpRejectAndDontRequeueException[] to signal the message should be rejected.
diff --git a/documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/testing/testcontainers.adoc b/documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/testing/testcontainers.adoc
index 4a71a35fc804..c14ac02ad517 100644
--- a/documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/testing/testcontainers.adoc
+++ b/documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/testing/testcontainers.adoc
@@ -173,7 +173,7 @@ javadoc:org.testcontainers.clickhouse.ClickHouseContainer[],
javadoc:{url-testcontainers-mariadb-javadoc}/org.testcontainers.mariadb.MariaDBContainer[], javadoc:{url-testcontainers-mssqlserver-javadoc}/org.testcontainers.mssqlserver.MSSQLServerContainer[], javadoc:{url-testcontainers-mysql-javadoc}/org.testcontainers.mysql.MySQLContainer[],
javadoc:org.testcontainers.oracle.OracleContainer[OracleContainer (free)], javadoc:{url-testcontainers-oracle-xe-javadoc}/org.testcontainers.containers.OracleContainer[OracleContainer (XE)] or javadoc:{url-testcontainers-postgresql-javadoc}/org.testcontainers.postgresql.PostgreSQLContainer[]
-| javadoc:org.springframework.boot.amqp.autoconfigure.RabbitConnectionDetails[]
+| javadoc:org.springframework.boot.rabbitmq.autoconfigure.RabbitConnectionDetails[]
| Containers of type javadoc:{url-testcontainers-rabbitmq-javadoc}/org.testcontainers.rabbitmq.RabbitMQContainer[]
| javadoc:org.springframework.boot.amqp.autoconfigure.RabbitStreamConnectionDetails[]
diff --git a/documentation/spring-boot-docs/src/main/java/org/springframework/boot/docs/messaging/amqp/receiving/custom/MyRabbitConfiguration.java b/documentation/spring-boot-docs/src/main/java/org/springframework/boot/docs/messaging/amqp/receiving/custom/MyRabbitConfiguration.java
index e109d5de244a..172c9cbba0d1 100644
--- a/documentation/spring-boot-docs/src/main/java/org/springframework/boot/docs/messaging/amqp/receiving/custom/MyRabbitConfiguration.java
+++ b/documentation/spring-boot-docs/src/main/java/org/springframework/boot/docs/messaging/amqp/receiving/custom/MyRabbitConfiguration.java
@@ -18,7 +18,7 @@
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
-import org.springframework.boot.amqp.autoconfigure.SimpleRabbitListenerContainerFactoryConfigurer;
+import org.springframework.boot.rabbitmq.autoconfigure.SimpleRabbitListenerContainerFactoryConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
diff --git a/documentation/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/messaging/amqp/receiving/custom/MyRabbitConfiguration.kt b/documentation/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/messaging/amqp/receiving/custom/MyRabbitConfiguration.kt
index 4f1c80f38666..95ca6f610039 100644
--- a/documentation/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/messaging/amqp/receiving/custom/MyRabbitConfiguration.kt
+++ b/documentation/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/messaging/amqp/receiving/custom/MyRabbitConfiguration.kt
@@ -19,7 +19,7 @@ package org.springframework.boot.docs.messaging.amqp.receiving.custom
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory
import org.springframework.amqp.rabbit.connection.ConnectionFactory
-import org.springframework.boot.amqp.autoconfigure.SimpleRabbitListenerContainerFactoryConfigurer
+import org.springframework.boot.rabbitmq.autoconfigure.SimpleRabbitListenerContainerFactoryConfigurer
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
diff --git a/module/spring-boot-amqp/build.gradle b/module/spring-boot-amqp/build.gradle
index 0152cb160b86..edd172e77c6b 100644
--- a/module/spring-boot-amqp/build.gradle
+++ b/module/spring-boot-amqp/build.gradle
@@ -28,7 +28,7 @@ description = "Spring Boot AMQP"
dependencies {
api(project(":core:spring-boot"))
api("org.springframework:spring-messaging")
- api("org.springframework.amqp:spring-rabbit")
+ api("org.springframework.amqp:spring-rabbitmq-client")
compileOnly("com.fasterxml.jackson.core:jackson-annotations")
diff --git a/module/spring-boot-amqp/src/dockerTest/java/org/springframework/boot/amqp/testcontainers/RabbitContainerConnectionDetailsFactoryIntegrationTests.java b/module/spring-boot-amqp/src/dockerTest/java/org/springframework/boot/amqp/testcontainers/RabbitContainerConnectionDetailsFactoryIntegrationTests.java
index ea80da8d9bf3..ab4cf8da98ca 100644
--- a/module/spring-boot-amqp/src/dockerTest/java/org/springframework/boot/amqp/testcontainers/RabbitContainerConnectionDetailsFactoryIntegrationTests.java
+++ b/module/spring-boot-amqp/src/dockerTest/java/org/springframework/boot/amqp/testcontainers/RabbitContainerConnectionDetailsFactoryIntegrationTests.java
@@ -28,9 +28,9 @@
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
-import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.amqp.rabbitmq.client.RabbitAmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.amqp.autoconfigure.RabbitAutoConfiguration;
+import org.springframework.boot.amqp.autoconfigure.RabbitAmqpAutoConfiguration;
import org.springframework.boot.amqp.autoconfigure.RabbitConnectionDetails;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
@@ -60,7 +60,7 @@ class RabbitContainerConnectionDetailsFactoryIntegrationTests {
private RabbitConnectionDetails connectionDetails;
@Autowired
- private RabbitTemplate rabbitTemplate;
+ private RabbitAmqpTemplate rabbitAmqpTemplate;
@Autowired
private TestListener listener;
@@ -68,13 +68,13 @@ class RabbitContainerConnectionDetailsFactoryIntegrationTests {
@Test
void connectionCanBeMadeToRabbitContainer() {
assertThat(this.connectionDetails).isNotNull();
- this.rabbitTemplate.convertAndSend("test", "message");
+ this.rabbitAmqpTemplate.convertAndSend("test", "message");
Awaitility.waitAtMost(Duration.ofMinutes(4))
.untilAsserted(() -> assertThat(this.listener.messages).containsExactly("message"));
}
@Configuration(proxyBeanMethods = false)
- @ImportAutoConfiguration(RabbitAutoConfiguration.class)
+ @ImportAutoConfiguration(RabbitAmqpAutoConfiguration.class)
static class TestConfiguration {
@Bean
diff --git a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/AmqpEnvironmentBuilderCustomizer.java b/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/AmqpEnvironmentBuilderCustomizer.java
new file mode 100644
index 000000000000..1403d61f19ea
--- /dev/null
+++ b/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/AmqpEnvironmentBuilderCustomizer.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2012-present 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
+ *
+ * https://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.amqp.autoconfigure;
+
+import com.rabbitmq.client.amqp.Environment;
+import com.rabbitmq.client.amqp.impl.AmqpEnvironmentBuilder;
+
+/**
+ * Callback interface that can be implemented by beans wishing to customize the
+ * auto-configured {@link Environment} that is created by an
+ * {@link AmqpEnvironmentBuilder}.
+ *
+ * @author Eddú Meléndez
+ * @since 4.1.0
+ */
+@FunctionalInterface
+public interface AmqpEnvironmentBuilderCustomizer {
+
+ /**
+ * Customize the {@code AmqpEnvironmentBuilder}.
+ * @param builder the builder to customize
+ */
+ void customize(AmqpEnvironmentBuilder builder);
+
+}
diff --git a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/RabbitAmqpAutoConfiguration.java b/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/RabbitAmqpAutoConfiguration.java
new file mode 100644
index 000000000000..39f4979c2bef
--- /dev/null
+++ b/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/RabbitAmqpAutoConfiguration.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2012-present 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
+ *
+ * https://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.amqp.autoconfigure;
+
+import com.rabbitmq.client.amqp.Connection;
+import com.rabbitmq.client.amqp.CredentialsProvider;
+import com.rabbitmq.client.amqp.Environment;
+import com.rabbitmq.client.amqp.impl.AmqpEnvironmentBuilder;
+import com.rabbitmq.client.amqp.impl.AmqpEnvironmentBuilder.EnvironmentConnectionSettings;
+
+import org.springframework.amqp.rabbit.config.ContainerCustomizer;
+import org.springframework.amqp.rabbitmq.client.AmqpConnectionFactory;
+import org.springframework.amqp.rabbitmq.client.RabbitAmqpAdmin;
+import org.springframework.amqp.rabbitmq.client.RabbitAmqpTemplate;
+import org.springframework.amqp.rabbitmq.client.SingleAmqpConnectionFactory;
+import org.springframework.amqp.rabbitmq.client.config.RabbitAmqpListenerContainerFactory;
+import org.springframework.amqp.rabbitmq.client.listener.RabbitAmqpListenerContainer;
+import org.springframework.amqp.support.converter.MessageConverter;
+import org.springframework.beans.factory.ObjectProvider;
+import org.springframework.boot.amqp.autoconfigure.RabbitConnectionDetails.Address;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+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.EnableConfigurationProperties;
+import org.springframework.boot.context.properties.PropertyMapper;
+import org.springframework.boot.ssl.SslBundles;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Import;
+
+/**
+ * {@link EnableAutoConfiguration Auto-configuration} for {@link RabbitAmqpTemplate}.
+ *
+ * @author Eddú Meléndez
+ * @since 4.1.0
+ */
+@AutoConfiguration
+@ConditionalOnClass({ RabbitAmqpTemplate.class, Connection.class })
+@EnableConfigurationProperties(RabbitProperties.class)
+@Import(RabbitAnnotationDrivenConfiguration.class)
+public final class RabbitAmqpAutoConfiguration {
+
+ private final RabbitProperties properties;
+
+ RabbitAmqpAutoConfiguration(RabbitProperties properties) {
+ this.properties = properties;
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ RabbitConnectionDetails rabbitConnectionDetails(ObjectProvider sslBundles) {
+ return new PropertiesRabbitConnectionDetails(this.properties, sslBundles.getIfAvailable());
+ }
+
+ @Bean(name = "rabbitListenerContainerFactory")
+ @ConditionalOnMissingBean(name = "rabbitListenerContainerFactory")
+ RabbitAmqpListenerContainerFactory rabbitAmqpListenerContainerFactory(AmqpConnectionFactory connectionFactory,
+ ObjectProvider> amqpContainerCustomizer) {
+ RabbitAmqpListenerContainerFactory factory = new RabbitAmqpListenerContainerFactory(connectionFactory);
+ amqpContainerCustomizer.ifUnique(factory::setContainerCustomizer);
+
+ RabbitProperties.AmqpContainer configuration = this.properties.getListener().getSimple();
+ factory.setObservationEnabled(configuration.isObservationEnabled());
+ return factory;
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ Environment rabbitAmqpEnvironment(RabbitConnectionDetails connectionDetails,
+ ObjectProvider customizers,
+ ObjectProvider credentialsProvider) {
+ PropertyMapper map = PropertyMapper.get();
+ EnvironmentConnectionSettings environmentConnectionSettings = new AmqpEnvironmentBuilder().connectionSettings();
+ Address address = connectionDetails.getFirstAddress();
+ map.from(address::host).to(environmentConnectionSettings::host);
+ map.from(address::port).to(environmentConnectionSettings::port);
+ map.from(connectionDetails::getUsername).to(environmentConnectionSettings::username);
+ map.from(connectionDetails::getPassword).to(environmentConnectionSettings::password);
+ map.from(connectionDetails::getVirtualHost).to(environmentConnectionSettings::virtualHost);
+ map.from(credentialsProvider::getIfAvailable).to(environmentConnectionSettings::credentialsProvider);
+
+ AmqpEnvironmentBuilder builder = environmentConnectionSettings.environmentBuilder();
+ customizers.orderedStream().forEach((customizer) -> customizer.customize(builder));
+ return builder.build();
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ AmqpConnectionFactory amqpConnectionFactory(Environment environment) {
+ return new SingleAmqpConnectionFactory(environment);
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ RabbitAmqpTemplate rabbitAmqpTemplate(AmqpConnectionFactory connectionFactory,
+ ObjectProvider customizers,
+ ObjectProvider messageConverter) {
+ RabbitAmqpTemplate rabbitAmqpTemplate = new RabbitAmqpTemplate(connectionFactory);
+ if (messageConverter.getIfAvailable() != null) {
+ rabbitAmqpTemplate.setMessageConverter(messageConverter.getIfAvailable());
+ }
+ RabbitProperties.Template templateProperties = this.properties.getTemplate();
+
+ PropertyMapper map = PropertyMapper.get();
+ map.from(templateProperties::getDefaultReceiveQueue).to(rabbitAmqpTemplate::setReceiveQueue);
+ map.from(templateProperties::getExchange).to(rabbitAmqpTemplate::setExchange);
+ map.from(templateProperties::getRoutingKey).to(rabbitAmqpTemplate::setRoutingKey);
+
+ customizers.orderedStream().forEach((customizer) -> customizer.customize(rabbitAmqpTemplate));
+ return rabbitAmqpTemplate;
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ RabbitAmqpAdmin rabbitAmqpAdmin(AmqpConnectionFactory connectionFactory) {
+ return new RabbitAmqpAdmin(connectionFactory);
+ }
+
+}
diff --git a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/RabbitAmqpTemplateCustomizer.java b/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/RabbitAmqpTemplateCustomizer.java
new file mode 100644
index 000000000000..e1eb2404cbb2
--- /dev/null
+++ b/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/RabbitAmqpTemplateCustomizer.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2012-present 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
+ *
+ * https://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.amqp.autoconfigure;
+
+import org.springframework.amqp.rabbitmq.client.RabbitAmqpTemplate;
+
+/**
+ * Callback interface that can be used to customize a {@link RabbitAmqpTemplate}.
+ *
+ * @author Eddú Meléndez
+ * @since 4.0.0
+ */
+@FunctionalInterface
+public interface RabbitAmqpTemplateCustomizer {
+
+ /**
+ * Callback to customize a {@link RabbitAmqpTemplate} instance.
+ * @param rabbitAmqpTemplate the rabbitAmqpTemplate to customize
+ */
+ void customize(RabbitAmqpTemplate rabbitAmqpTemplate);
+
+}
diff --git a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/RabbitAnnotationDrivenConfiguration.java b/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/RabbitAnnotationDrivenConfiguration.java
index 2c1b260abe0a..c2c766c096e7 100644
--- a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/RabbitAnnotationDrivenConfiguration.java
+++ b/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/RabbitAnnotationDrivenConfiguration.java
@@ -17,134 +17,20 @@
package org.springframework.boot.amqp.autoconfigure;
import org.springframework.amqp.rabbit.annotation.EnableRabbit;
-import org.springframework.amqp.rabbit.config.ContainerCustomizer;
-import org.springframework.amqp.rabbit.config.DirectRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.config.RabbitListenerConfigUtils;
-import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
-import org.springframework.amqp.rabbit.connection.ConnectionFactory;
-import org.springframework.amqp.rabbit.listener.DirectMessageListenerContainer;
-import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
-import org.springframework.amqp.rabbit.retry.MessageRecoverer;
-import org.springframework.amqp.rabbit.support.micrometer.RabbitListenerObservationConvention;
-import org.springframework.amqp.support.converter.MessageConverter;
-import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnThreading;
-import org.springframework.boot.thread.Threading;
-import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
-import org.springframework.core.task.VirtualThreadTaskExecutor;
/**
* Configuration for Spring AMQP annotation driven endpoints.
*
- * @author Stephane Nicoll
- * @author Josh Thornhill
- * @author Moritz Halbritter
+ * @author Eddú Meléndez
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(EnableRabbit.class)
class RabbitAnnotationDrivenConfiguration {
- private final ObjectProvider messageConverter;
-
- private final ObjectProvider messageRecoverer;
-
- private final ObjectProvider retrySettingsCustomizers;
-
- private final RabbitProperties properties;
-
- private final ObjectProvider observationConvention;
-
- RabbitAnnotationDrivenConfiguration(ObjectProvider messageConverter,
- ObjectProvider messageRecoverer,
- ObjectProvider retrySettingsCustomizers,
- ObjectProvider observationConvention, RabbitProperties properties) {
- this.messageConverter = messageConverter;
- this.messageRecoverer = messageRecoverer;
- this.retrySettingsCustomizers = retrySettingsCustomizers;
- this.observationConvention = observationConvention;
- this.properties = properties;
- }
-
- @Bean
- @ConditionalOnMissingBean
- @ConditionalOnThreading(Threading.PLATFORM)
- SimpleRabbitListenerContainerFactoryConfigurer simpleRabbitListenerContainerFactoryConfigurer() {
- return simpleListenerConfigurer();
- }
-
- @Bean(name = "simpleRabbitListenerContainerFactoryConfigurer")
- @ConditionalOnMissingBean
- @ConditionalOnThreading(Threading.VIRTUAL)
- SimpleRabbitListenerContainerFactoryConfigurer simpleRabbitListenerContainerFactoryConfigurerVirtualThreads() {
- SimpleRabbitListenerContainerFactoryConfigurer configurer = simpleListenerConfigurer();
- configurer.setTaskExecutor(new VirtualThreadTaskExecutor("rabbit-simple-"));
- return configurer;
- }
-
- @Bean(name = "rabbitListenerContainerFactory")
- @ConditionalOnMissingBean(name = "rabbitListenerContainerFactory")
- @ConditionalOnProperty(name = "spring.rabbitmq.listener.type", havingValue = "simple", matchIfMissing = true)
- SimpleRabbitListenerContainerFactory simpleRabbitListenerContainerFactory(
- SimpleRabbitListenerContainerFactoryConfigurer configurer, ConnectionFactory connectionFactory,
- ObjectProvider> simpleContainerCustomizer) {
- SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
- configurer.configure(factory, connectionFactory);
- simpleContainerCustomizer.ifUnique(factory::setContainerCustomizer);
- return factory;
- }
-
- @Bean
- @ConditionalOnMissingBean
- @ConditionalOnThreading(Threading.PLATFORM)
- DirectRabbitListenerContainerFactoryConfigurer directRabbitListenerContainerFactoryConfigurer() {
- return directListenerConfigurer();
- }
-
- @Bean(name = "directRabbitListenerContainerFactoryConfigurer")
- @ConditionalOnMissingBean
- @ConditionalOnThreading(Threading.VIRTUAL)
- DirectRabbitListenerContainerFactoryConfigurer directRabbitListenerContainerFactoryConfigurerVirtualThreads() {
- DirectRabbitListenerContainerFactoryConfigurer configurer = directListenerConfigurer();
- configurer.setTaskExecutor(new VirtualThreadTaskExecutor("rabbit-direct-"));
- return configurer;
- }
-
- @Bean(name = "rabbitListenerContainerFactory")
- @ConditionalOnMissingBean(name = "rabbitListenerContainerFactory")
- @ConditionalOnProperty(name = "spring.rabbitmq.listener.type", havingValue = "direct")
- DirectRabbitListenerContainerFactory directRabbitListenerContainerFactory(
- DirectRabbitListenerContainerFactoryConfigurer configurer, ConnectionFactory connectionFactory,
- ObjectProvider> directContainerCustomizer) {
- DirectRabbitListenerContainerFactory factory = new DirectRabbitListenerContainerFactory();
- configurer.configure(factory, connectionFactory);
- directContainerCustomizer.ifUnique(factory::setContainerCustomizer);
- return factory;
- }
-
- private SimpleRabbitListenerContainerFactoryConfigurer simpleListenerConfigurer() {
- SimpleRabbitListenerContainerFactoryConfigurer configurer = new SimpleRabbitListenerContainerFactoryConfigurer(
- this.properties);
- configurer.setMessageConverter(this.messageConverter.getIfUnique());
- configurer.setMessageRecoverer(this.messageRecoverer.getIfUnique());
- configurer.setObservationConvention(this.observationConvention.getIfUnique());
- configurer.setRetrySettingsCustomizers(this.retrySettingsCustomizers.orderedStream().toList());
- return configurer;
- }
-
- private DirectRabbitListenerContainerFactoryConfigurer directListenerConfigurer() {
- DirectRabbitListenerContainerFactoryConfigurer configurer = new DirectRabbitListenerContainerFactoryConfigurer(
- this.properties);
- configurer.setMessageConverter(this.messageConverter.getIfUnique());
- configurer.setMessageRecoverer(this.messageRecoverer.getIfUnique());
- configurer.setObservationConvention(this.observationConvention.getIfUnique());
- configurer.setRetrySettingsCustomizers(this.retrySettingsCustomizers.orderedStream().toList());
- return configurer;
- }
-
@Configuration(proxyBeanMethods = false)
@EnableRabbit
@ConditionalOnMissingBean(name = RabbitListenerConfigUtils.RABBIT_LISTENER_ANNOTATION_PROCESSOR_BEAN_NAME)
diff --git a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/docker/compose/RabbitDockerComposeConnectionDetailsFactory.java b/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/docker/compose/RabbitDockerComposeConnectionDetailsFactory.java
index a5564994cb76..8d3180126f71 100644
--- a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/docker/compose/RabbitDockerComposeConnectionDetailsFactory.java
+++ b/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/docker/compose/RabbitDockerComposeConnectionDetailsFactory.java
@@ -21,14 +21,13 @@
import org.jspecify.annotations.Nullable;
import org.springframework.boot.amqp.autoconfigure.RabbitConnectionDetails;
-import org.springframework.boot.amqp.autoconfigure.RabbitStreamConnectionDetails;
import org.springframework.boot.docker.compose.core.RunningService;
import org.springframework.boot.docker.compose.service.connection.DockerComposeConnectionDetailsFactory;
import org.springframework.boot.docker.compose.service.connection.DockerComposeConnectionSource;
/**
- * {@link DockerComposeConnectionDetailsFactory} to create
- * {@link RabbitStreamConnectionDetails} for a {@code rabbitmq} service.
+ * {@link DockerComposeConnectionDetailsFactory} to create {@link RabbitConnectionDetails}
+ * for a {@code rabbitmq} service.
*
* @author Andy Wilkinson
*/
diff --git a/module/spring-boot-amqp/src/main/resources/META-INF/spring.factories b/module/spring-boot-amqp/src/main/resources/META-INF/spring.factories
index 17fb2095415a..f086b1a88ce8 100644
--- a/module/spring-boot-amqp/src/main/resources/META-INF/spring.factories
+++ b/module/spring-boot-amqp/src/main/resources/META-INF/spring.factories
@@ -1,8 +1,5 @@
# Connection Details Factories
org.springframework.boot.autoconfigure.service.connection.ConnectionDetailsFactory=\
org.springframework.boot.amqp.docker.compose.RabbitDockerComposeConnectionDetailsFactory,\
-org.springframework.boot.amqp.docker.compose.RabbitStreamDockerComposeConnectionDetailsFactory,\
org.springframework.boot.amqp.testcontainers.DeprecatedRabbitContainerConnectionDetailsFactory,\
-org.springframework.boot.amqp.testcontainers.RabbitContainerConnectionDetailsFactory,\
-org.springframework.boot.amqp.testcontainers.RabbitStreamContainerConnectionDetailsFactory
-
+org.springframework.boot.amqp.testcontainers.RabbitContainerConnectionDetailsFactory
diff --git a/module/spring-boot-amqp/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/module/spring-boot-amqp/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
index daf8ae3ba45f..050f5729e283 100644
--- a/module/spring-boot-amqp/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
+++ b/module/spring-boot-amqp/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -1,3 +1 @@
-org.springframework.boot.amqp.autoconfigure.RabbitAutoConfiguration
-org.springframework.boot.amqp.autoconfigure.health.RabbitHealthContributorAutoConfiguration
-org.springframework.boot.amqp.autoconfigure.metrics.RabbitMetricsAutoConfiguration
\ No newline at end of file
+org.springframework.boot.amqp.autoconfigure.RabbitAmqpAutoConfiguration
\ No newline at end of file
diff --git a/module/spring-boot-amqp/src/test/java/org/springframework/boot/amqp/autoconfigure/RabbitAmqpAutoConfigurationTests.java b/module/spring-boot-amqp/src/test/java/org/springframework/boot/amqp/autoconfigure/RabbitAmqpAutoConfigurationTests.java
new file mode 100644
index 000000000000..11ff3588403d
--- /dev/null
+++ b/module/spring-boot-amqp/src/test/java/org/springframework/boot/amqp/autoconfigure/RabbitAmqpAutoConfigurationTests.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright 2012-present 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
+ *
+ * https://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.amqp.autoconfigure;
+
+import org.aopalliance.aop.Advice;
+import org.junit.jupiter.api.Test;
+import org.mockito.InOrder;
+
+import org.springframework.amqp.core.Message;
+import org.springframework.amqp.core.MessageProperties;
+import org.springframework.amqp.rabbit.annotation.RabbitListener;
+import org.springframework.amqp.rabbit.config.BaseRabbitListenerContainerFactory;
+import org.springframework.amqp.rabbit.config.ContainerCustomizer;
+import org.springframework.amqp.rabbitmq.client.AmqpConnectionFactory;
+import org.springframework.amqp.rabbitmq.client.RabbitAmqpAdmin;
+import org.springframework.amqp.rabbitmq.client.RabbitAmqpTemplate;
+import org.springframework.amqp.rabbitmq.client.config.RabbitAmqpListenerContainerFactory;
+import org.springframework.amqp.rabbitmq.client.listener.RabbitAmqpListenerContainer;
+import org.springframework.amqp.support.converter.MessageConversionException;
+import org.springframework.amqp.support.converter.MessageConverter;
+import org.springframework.boot.autoconfigure.AutoConfigurations;
+import org.springframework.boot.test.context.runner.ApplicationContextRunner;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+import org.springframework.core.Ordered;
+import org.springframework.core.annotation.Order;
+import org.springframework.core.retry.RetryPolicy;
+import org.springframework.core.retry.RetryTemplate;
+import org.springframework.test.util.ReflectionTestUtils;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.BDDMockito.then;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
+
+/**
+ * Tests for {@link RabbitAmqpAutoConfiguration}.
+ *
+ * @author Eddú Meléndez
+ */
+class RabbitAmqpAutoConfigurationTests {
+
+ private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
+ .withConfiguration(AutoConfigurations.of(RabbitAmqpAutoConfiguration.class));
+
+ @Test
+ void testDefaultRabbitAmqpConfiguration() {
+ this.contextRunner.run((context) -> {
+ RabbitAmqpListenerContainerFactory listenerContainerFactory = context
+ .getBean(RabbitAmqpListenerContainerFactory.class);
+ AmqpConnectionFactory connectionFactory = context.getBean(AmqpConnectionFactory.class);
+ RabbitAmqpTemplate rabbitAmqpTemplate = context.getBean(RabbitAmqpTemplate.class);
+ RabbitAmqpAdmin rabbitAmqpAdmin = context.getBean(RabbitAmqpAdmin.class);
+
+ assertThat(listenerContainerFactory).isNotNull();
+ assertThat(listenerContainerFactory).extracting("containerCustomizer").isNull();
+ assertThat(connectionFactory).isNotNull();
+ assertThat(rabbitAmqpTemplate).isNotNull();
+ assertThat(rabbitAmqpAdmin).isNotNull();
+ });
+ }
+
+ @Test
+ void whenMultipleRabbitAmqpTemplateCustomizersAreDefinedThenTheyAreCalledInOrder() {
+ this.contextRunner.withUserConfiguration(MultipleRabbitAmqpTemplateCustomizersConfiguration.class)
+ .run((context) -> {
+ RabbitAmqpTemplateCustomizer firstCustomizer = context.getBean("firstCustomizer",
+ RabbitAmqpTemplateCustomizer.class);
+ RabbitAmqpTemplateCustomizer secondCustomizer = context.getBean("secondCustomizer",
+ RabbitAmqpTemplateCustomizer.class);
+ InOrder inOrder = inOrder(firstCustomizer, secondCustomizer);
+ RabbitAmqpTemplate template = context.getBean(RabbitAmqpTemplate.class);
+ then(firstCustomizer).should(inOrder).customize(template);
+ then(secondCustomizer).should(inOrder).customize(template);
+ inOrder.verifyNoMoreInteractions();
+ });
+ }
+
+ private void assertListenerRetryTemplate(BaseRabbitListenerContainerFactory> rabbitListenerContainerFactory,
+ RetryPolicy retryPolicy) {
+ Advice[] adviceChain = rabbitListenerContainerFactory.getAdviceChain();
+ assertThat(adviceChain).isNotNull();
+ assertThat(adviceChain).hasSize(1);
+ Advice advice = adviceChain[0];
+ RetryTemplate retryTemplate = (RetryTemplate) ReflectionTestUtils.getField(advice, "retryOperations");
+ assertThat(retryTemplate).hasFieldOrPropertyWithValue("retryPolicy", retryPolicy);
+ }
+
+ @Test
+ void testListenerContainerFactoryWithContainerCustomizer() {
+ this.contextRunner.withUserConfiguration(AmqpContainerCustomizerConfiguration.class).run((context) -> {
+ RabbitAmqpListenerContainerFactory listenerContainerFactory = context
+ .getBean(RabbitAmqpListenerContainerFactory.class);
+
+ assertThat(listenerContainerFactory).isNotNull();
+ assertThat(listenerContainerFactory).extracting("containerCustomizer").isNotNull();
+ });
+ }
+
+ @Configuration(proxyBeanMethods = false)
+ static class MultipleRabbitAmqpTemplateCustomizersConfiguration {
+
+ @Bean
+ @Order(Ordered.LOWEST_PRECEDENCE)
+ RabbitAmqpTemplateCustomizer secondCustomizer() {
+ return mock(RabbitAmqpTemplateCustomizer.class);
+ }
+
+ @Bean
+ @Order(0)
+ RabbitAmqpTemplateCustomizer firstCustomizer() {
+ return mock(RabbitAmqpTemplateCustomizer.class);
+ }
+
+ }
+
+ @Import(TestListener.class)
+ @Configuration(proxyBeanMethods = false)
+ static class AmqpContainerCustomizerConfiguration {
+
+ @Bean
+ @SuppressWarnings("unchecked")
+ ContainerCustomizer customizer() {
+ return mock(ContainerCustomizer.class);
+ }
+
+ }
+
+ @Configuration
+ static class CustomMessageConverterConfiguration {
+
+ @Bean
+ MessageConverter messageConverter() {
+ return new MessageConverter() {
+
+ @Override
+ public Message toMessage(Object object, MessageProperties messageProperties)
+ throws MessageConversionException {
+ return new Message(object.toString().getBytes());
+ }
+
+ @Override
+ public Object fromMessage(Message message) throws MessageConversionException {
+ return new String(message.getBody());
+ }
+
+ };
+ }
+
+ }
+
+ static class TestListener {
+
+ @RabbitListener(queues = "test", autoStartup = "false")
+ void listen(String in) {
+ }
+
+ }
+
+}
diff --git a/module/spring-boot-rabbitmq/build.gradle b/module/spring-boot-rabbitmq/build.gradle
new file mode 100644
index 000000000000..fcc106775fb9
--- /dev/null
+++ b/module/spring-boot-rabbitmq/build.gradle
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2012-present 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
+ *
+ * https://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.
+ */
+
+plugins {
+ id "java-library"
+ id "org.springframework.boot.docker-test"
+ id "org.springframework.boot.auto-configuration"
+ id "org.springframework.boot.configuration-properties"
+ id "org.springframework.boot.deployed"
+ id "org.springframework.boot.optional-dependencies"
+}
+
+description = "Spring Boot RabbiqMQ"
+
+dependencies {
+ api(project(":core:spring-boot"))
+ api("org.springframework:spring-messaging")
+ api("org.springframework.amqp:spring-rabbit")
+
+ compileOnly("com.fasterxml.jackson.core:jackson-annotations")
+
+ implementation(project(":module:spring-boot-transaction"))
+
+ optional(project(":core:spring-boot-autoconfigure"))
+ optional(project(":core:spring-boot-docker-compose"))
+ optional(project(":core:spring-boot-testcontainers"))
+ optional(project(":module:spring-boot-health"))
+ optional(project(":module:spring-boot-micrometer-metrics"))
+ optional("io.micrometer:micrometer-core")
+ optional("org.springframework.amqp:spring-rabbit-stream")
+ optional("org.testcontainers:testcontainers-rabbitmq")
+
+ dockerTestImplementation(project(":test-support:spring-boot-docker-test-support"))
+ dockerTestImplementation(testFixtures(project(":core:spring-boot-docker-compose")))
+ dockerTestImplementation("ch.qos.logback:logback-classic")
+ dockerTestImplementation("org.testcontainers:testcontainers-junit-jupiter")
+
+ testCompileOnly("com.fasterxml.jackson.core:jackson-annotations")
+
+ testImplementation(project(":core:spring-boot-test"))
+ testImplementation(project(":test-support:spring-boot-test-support"))
+
+ testRuntimeOnly("ch.qos.logback:logback-classic")
+}
+
+tasks.named("compileTestJava") {
+ options.nullability.checking = "tests"
+}
+
+tasks.named("compileDockerTestJava") {
+ options.nullability.checking = "tests"
+}
diff --git a/module/spring-boot-amqp/src/dockerTest/java/org/springframework/boot/amqp/docker/compose/RabbitAndRabbitStreamDockerComposeConnectionDetailsFactoryIntegrationTests.java b/module/spring-boot-rabbitmq/src/dockerTest/java/org/springframework/boot/rabbitmq/docker/compose/RabbitAndRabbitStreamDockerComposeConnectionDetailsFactoryIntegrationTests.java
similarity index 89%
rename from module/spring-boot-amqp/src/dockerTest/java/org/springframework/boot/amqp/docker/compose/RabbitAndRabbitStreamDockerComposeConnectionDetailsFactoryIntegrationTests.java
rename to module/spring-boot-rabbitmq/src/dockerTest/java/org/springframework/boot/rabbitmq/docker/compose/RabbitAndRabbitStreamDockerComposeConnectionDetailsFactoryIntegrationTests.java
index 5b1c7797bbac..dcef4737265a 100644
--- a/module/spring-boot-amqp/src/dockerTest/java/org/springframework/boot/amqp/docker/compose/RabbitAndRabbitStreamDockerComposeConnectionDetailsFactoryIntegrationTests.java
+++ b/module/spring-boot-rabbitmq/src/dockerTest/java/org/springframework/boot/rabbitmq/docker/compose/RabbitAndRabbitStreamDockerComposeConnectionDetailsFactoryIntegrationTests.java
@@ -14,12 +14,12 @@
* limitations under the License.
*/
-package org.springframework.boot.amqp.docker.compose;
+package org.springframework.boot.rabbitmq.docker.compose;
-import org.springframework.boot.amqp.autoconfigure.RabbitConnectionDetails;
-import org.springframework.boot.amqp.autoconfigure.RabbitConnectionDetails.Address;
-import org.springframework.boot.amqp.autoconfigure.RabbitStreamConnectionDetails;
import org.springframework.boot.docker.compose.service.connection.test.DockerComposeTest;
+import org.springframework.boot.rabbitmq.autoconfigure.RabbitConnectionDetails;
+import org.springframework.boot.rabbitmq.autoconfigure.RabbitConnectionDetails.Address;
+import org.springframework.boot.rabbitmq.autoconfigure.RabbitStreamConnectionDetails;
import org.springframework.boot.testsupport.container.TestImage;
import static org.assertj.core.api.Assertions.assertThat;
diff --git a/module/spring-boot-rabbitmq/src/dockerTest/java/org/springframework/boot/rabbitmq/docker/compose/RabbitDockerComposeConnectionDetailsFactoryIntegrationTests.java b/module/spring-boot-rabbitmq/src/dockerTest/java/org/springframework/boot/rabbitmq/docker/compose/RabbitDockerComposeConnectionDetailsFactoryIntegrationTests.java
new file mode 100644
index 000000000000..eeb49157abf9
--- /dev/null
+++ b/module/spring-boot-rabbitmq/src/dockerTest/java/org/springframework/boot/rabbitmq/docker/compose/RabbitDockerComposeConnectionDetailsFactoryIntegrationTests.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2012-present 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
+ *
+ * https://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.rabbitmq.docker.compose;
+
+import org.springframework.boot.docker.compose.service.connection.test.DockerComposeTest;
+import org.springframework.boot.rabbitmq.autoconfigure.RabbitConnectionDetails;
+import org.springframework.boot.rabbitmq.autoconfigure.RabbitConnectionDetails.Address;
+import org.springframework.boot.testsupport.container.TestImage;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Integration tests for {@link RabbitDockerComposeConnectionDetailsFactory}.
+ *
+ * @author Moritz Halbritter
+ * @author Andy Wilkinson
+ * @author Phillip Webb
+ * @author Scott Frederick
+ */
+class RabbitDockerComposeConnectionDetailsFactoryIntegrationTests {
+
+ @DockerComposeTest(composeFile = "rabbit-compose.yaml", image = TestImage.RABBITMQ)
+ void runCreatesConnectionDetails(RabbitConnectionDetails connectionDetails) {
+ assertConnectionDetails(connectionDetails);
+ }
+
+ private void assertConnectionDetails(RabbitConnectionDetails connectionDetails) {
+ assertThat(connectionDetails.getUsername()).isEqualTo("myuser");
+ assertThat(connectionDetails.getPassword()).isEqualTo("secret");
+ assertThat(connectionDetails.getVirtualHost()).isEqualTo("/");
+ assertThat(connectionDetails.getAddresses()).hasSize(1);
+ Address address = connectionDetails.getFirstAddress();
+ assertThat(address.host()).isNotNull();
+ assertThat(address.port()).isGreaterThan(0);
+ }
+
+}
diff --git a/module/spring-boot-amqp/src/dockerTest/java/org/springframework/boot/amqp/docker/compose/RabbitStreamDockerComposeConnectionDetailsFactoryIntegrationTests.java b/module/spring-boot-rabbitmq/src/dockerTest/java/org/springframework/boot/rabbitmq/docker/compose/RabbitStreamDockerComposeConnectionDetailsFactoryIntegrationTests.java
similarity index 92%
rename from module/spring-boot-amqp/src/dockerTest/java/org/springframework/boot/amqp/docker/compose/RabbitStreamDockerComposeConnectionDetailsFactoryIntegrationTests.java
rename to module/spring-boot-rabbitmq/src/dockerTest/java/org/springframework/boot/rabbitmq/docker/compose/RabbitStreamDockerComposeConnectionDetailsFactoryIntegrationTests.java
index 1547fbf825c4..7e6092db4285 100644
--- a/module/spring-boot-amqp/src/dockerTest/java/org/springframework/boot/amqp/docker/compose/RabbitStreamDockerComposeConnectionDetailsFactoryIntegrationTests.java
+++ b/module/spring-boot-rabbitmq/src/dockerTest/java/org/springframework/boot/rabbitmq/docker/compose/RabbitStreamDockerComposeConnectionDetailsFactoryIntegrationTests.java
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-package org.springframework.boot.amqp.docker.compose;
+package org.springframework.boot.rabbitmq.docker.compose;
-import org.springframework.boot.amqp.autoconfigure.RabbitStreamConnectionDetails;
import org.springframework.boot.docker.compose.service.connection.test.DockerComposeTest;
+import org.springframework.boot.rabbitmq.autoconfigure.RabbitStreamConnectionDetails;
import org.springframework.boot.testsupport.container.TestImage;
import static org.assertj.core.api.Assertions.assertThat;
diff --git a/module/spring-boot-amqp/src/dockerTest/java/org/springframework/boot/amqp/docker/compose/SingleServiceRabbitAndRabbitStreamDockerComposeConnectionDetailsFactoryIntegrationTests.java b/module/spring-boot-rabbitmq/src/dockerTest/java/org/springframework/boot/rabbitmq/docker/compose/SingleServiceRabbitAndRabbitStreamDockerComposeConnectionDetailsFactoryIntegrationTests.java
similarity index 88%
rename from module/spring-boot-amqp/src/dockerTest/java/org/springframework/boot/amqp/docker/compose/SingleServiceRabbitAndRabbitStreamDockerComposeConnectionDetailsFactoryIntegrationTests.java
rename to module/spring-boot-rabbitmq/src/dockerTest/java/org/springframework/boot/rabbitmq/docker/compose/SingleServiceRabbitAndRabbitStreamDockerComposeConnectionDetailsFactoryIntegrationTests.java
index d9f077bc21cd..ae9d61597f63 100644
--- a/module/spring-boot-amqp/src/dockerTest/java/org/springframework/boot/amqp/docker/compose/SingleServiceRabbitAndRabbitStreamDockerComposeConnectionDetailsFactoryIntegrationTests.java
+++ b/module/spring-boot-rabbitmq/src/dockerTest/java/org/springframework/boot/rabbitmq/docker/compose/SingleServiceRabbitAndRabbitStreamDockerComposeConnectionDetailsFactoryIntegrationTests.java
@@ -14,12 +14,12 @@
* limitations under the License.
*/
-package org.springframework.boot.amqp.docker.compose;
+package org.springframework.boot.rabbitmq.docker.compose;
-import org.springframework.boot.amqp.autoconfigure.RabbitConnectionDetails;
-import org.springframework.boot.amqp.autoconfigure.RabbitConnectionDetails.Address;
-import org.springframework.boot.amqp.autoconfigure.RabbitStreamConnectionDetails;
import org.springframework.boot.docker.compose.service.connection.test.DockerComposeTest;
+import org.springframework.boot.rabbitmq.autoconfigure.RabbitConnectionDetails;
+import org.springframework.boot.rabbitmq.autoconfigure.RabbitConnectionDetails.Address;
+import org.springframework.boot.rabbitmq.autoconfigure.RabbitStreamConnectionDetails;
import org.springframework.boot.testsupport.container.TestImage;
import static org.assertj.core.api.Assertions.assertThat;
diff --git a/module/spring-boot-amqp/src/dockerTest/java/org/springframework/boot/amqp/testcontainers/DeprecatedRabbitContainerConnectionDetailsFactoryIntegrationTests.java b/module/spring-boot-rabbitmq/src/dockerTest/java/org/springframework/boot/rabbitmq/testcontainers/DeprecatedRabbitContainerConnectionDetailsFactoryIntegrationTests.java
similarity index 93%
rename from module/spring-boot-amqp/src/dockerTest/java/org/springframework/boot/amqp/testcontainers/DeprecatedRabbitContainerConnectionDetailsFactoryIntegrationTests.java
rename to module/spring-boot-rabbitmq/src/dockerTest/java/org/springframework/boot/rabbitmq/testcontainers/DeprecatedRabbitContainerConnectionDetailsFactoryIntegrationTests.java
index 51e32711184d..91aed53b74b5 100644
--- a/module/spring-boot-amqp/src/dockerTest/java/org/springframework/boot/amqp/testcontainers/DeprecatedRabbitContainerConnectionDetailsFactoryIntegrationTests.java
+++ b/module/spring-boot-rabbitmq/src/dockerTest/java/org/springframework/boot/rabbitmq/testcontainers/DeprecatedRabbitContainerConnectionDetailsFactoryIntegrationTests.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.boot.amqp.testcontainers;
+package org.springframework.boot.rabbitmq.testcontainers;
import java.time.Duration;
import java.util.ArrayList;
@@ -30,9 +30,9 @@
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.amqp.autoconfigure.RabbitAutoConfiguration;
-import org.springframework.boot.amqp.autoconfigure.RabbitConnectionDetails;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
+import org.springframework.boot.rabbitmq.autoconfigure.RabbitAutoConfiguration;
+import org.springframework.boot.rabbitmq.autoconfigure.RabbitConnectionDetails;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.boot.testsupport.container.TestImage;
import org.springframework.context.annotation.Bean;
diff --git a/module/spring-boot-rabbitmq/src/dockerTest/java/org/springframework/boot/rabbitmq/testcontainers/RabbitContainerConnectionDetailsFactoryIntegrationTests.java b/module/spring-boot-rabbitmq/src/dockerTest/java/org/springframework/boot/rabbitmq/testcontainers/RabbitContainerConnectionDetailsFactoryIntegrationTests.java
new file mode 100644
index 000000000000..0dda1bfa18d6
--- /dev/null
+++ b/module/spring-boot-rabbitmq/src/dockerTest/java/org/springframework/boot/rabbitmq/testcontainers/RabbitContainerConnectionDetailsFactoryIntegrationTests.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2012-present 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
+ *
+ * https://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.rabbitmq.testcontainers;
+
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.awaitility.Awaitility;
+import org.junit.jupiter.api.Test;
+import org.testcontainers.junit.jupiter.Container;
+import org.testcontainers.junit.jupiter.Testcontainers;
+import org.testcontainers.rabbitmq.RabbitMQContainer;
+
+import org.springframework.amqp.rabbit.annotation.Queue;
+import org.springframework.amqp.rabbit.annotation.RabbitListener;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
+import org.springframework.boot.rabbitmq.autoconfigure.RabbitAutoConfiguration;
+import org.springframework.boot.rabbitmq.autoconfigure.RabbitConnectionDetails;
+import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
+import org.springframework.boot.testsupport.container.TestImage;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link RabbitContainerConnectionDetailsFactory}.
+ *
+ * @author Moritz Halbritter
+ * @author Andy Wilkinson
+ * @author Phillip Webb
+ */
+@SpringJUnitConfig
+@Testcontainers(disabledWithoutDocker = true)
+class RabbitContainerConnectionDetailsFactoryIntegrationTests {
+
+ @Container
+ @ServiceConnection
+ static final RabbitMQContainer rabbit = TestImage.container(RabbitMQContainer.class);
+
+ @Autowired(required = false)
+ private RabbitConnectionDetails connectionDetails;
+
+ @Autowired
+ private RabbitTemplate rabbitTemplate;
+
+ @Autowired
+ private TestListener listener;
+
+ @Test
+ void connectionCanBeMadeToRabbitContainer() {
+ assertThat(this.connectionDetails).isNotNull();
+ this.rabbitTemplate.convertAndSend("test", "message");
+ Awaitility.waitAtMost(Duration.ofMinutes(4))
+ .untilAsserted(() -> assertThat(this.listener.messages).containsExactly("message"));
+
+ }
+
+ @Configuration(proxyBeanMethods = false)
+ @ImportAutoConfiguration(RabbitAutoConfiguration.class)
+ static class TestConfiguration {
+
+ @Bean
+ TestListener testListener() {
+ return new TestListener();
+ }
+
+ }
+
+ static class TestListener {
+
+ private final List messages = new ArrayList<>();
+
+ @RabbitListener(queuesToDeclare = @Queue("test"))
+ void processMessage(String message) {
+ this.messages.add(message);
+ }
+
+ }
+
+}
diff --git a/module/spring-boot-amqp/src/dockerTest/java/org/springframework/boot/amqp/testcontainers/RabbitStreamContainerConnectionDetailsFactoryIntegrationTests.java b/module/spring-boot-rabbitmq/src/dockerTest/java/org/springframework/boot/rabbitmq/testcontainers/RabbitStreamContainerConnectionDetailsFactoryIntegrationTests.java
similarity index 86%
rename from module/spring-boot-amqp/src/dockerTest/java/org/springframework/boot/amqp/testcontainers/RabbitStreamContainerConnectionDetailsFactoryIntegrationTests.java
rename to module/spring-boot-rabbitmq/src/dockerTest/java/org/springframework/boot/rabbitmq/testcontainers/RabbitStreamContainerConnectionDetailsFactoryIntegrationTests.java
index 1e65d213f2ac..8820db4606a9 100644
--- a/module/spring-boot-amqp/src/dockerTest/java/org/springframework/boot/amqp/testcontainers/RabbitStreamContainerConnectionDetailsFactoryIntegrationTests.java
+++ b/module/spring-boot-rabbitmq/src/dockerTest/java/org/springframework/boot/rabbitmq/testcontainers/RabbitStreamContainerConnectionDetailsFactoryIntegrationTests.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.boot.amqp.testcontainers;
+package org.springframework.boot.rabbitmq.testcontainers;
import java.time.Duration;
import java.util.ArrayList;
@@ -31,13 +31,13 @@
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.amqp.autoconfigure.EnvironmentBuilderCustomizer;
-import org.springframework.boot.amqp.autoconfigure.RabbitAutoConfiguration;
-import org.springframework.boot.amqp.autoconfigure.RabbitConnectionDetails;
-import org.springframework.boot.amqp.autoconfigure.RabbitStreamConnectionDetails;
-import org.springframework.boot.amqp.testcontainers.RabbitContainerConnectionDetailsFactory.RabbitMqContainerConnectionDetails;
-import org.springframework.boot.amqp.testcontainers.RabbitStreamContainerConnectionDetailsFactory.RabbitMqStreamContainerConnectionDetails;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
+import org.springframework.boot.rabbitmq.autoconfigure.EnvironmentBuilderCustomizer;
+import org.springframework.boot.rabbitmq.autoconfigure.RabbitAutoConfiguration;
+import org.springframework.boot.rabbitmq.autoconfigure.RabbitConnectionDetails;
+import org.springframework.boot.rabbitmq.autoconfigure.RabbitStreamConnectionDetails;
+import org.springframework.boot.rabbitmq.testcontainers.RabbitContainerConnectionDetailsFactory.RabbitMqContainerConnectionDetails;
+import org.springframework.boot.rabbitmq.testcontainers.RabbitStreamContainerConnectionDetailsFactory.RabbitMqStreamContainerConnectionDetails;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.boot.testsupport.container.TestImage;
import org.springframework.context.annotation.Bean;
diff --git a/module/spring-boot-amqp/src/dockerTest/java/org/springframework/boot/amqp/testcontainers/SeparateContainersRabbitAndRabbitStreamContainerConnectionDetailsFactoryIntegrationTests.java b/module/spring-boot-rabbitmq/src/dockerTest/java/org/springframework/boot/rabbitmq/testcontainers/SeparateContainersRabbitAndRabbitStreamContainerConnectionDetailsFactoryIntegrationTests.java
similarity index 89%
rename from module/spring-boot-amqp/src/dockerTest/java/org/springframework/boot/amqp/testcontainers/SeparateContainersRabbitAndRabbitStreamContainerConnectionDetailsFactoryIntegrationTests.java
rename to module/spring-boot-rabbitmq/src/dockerTest/java/org/springframework/boot/rabbitmq/testcontainers/SeparateContainersRabbitAndRabbitStreamContainerConnectionDetailsFactoryIntegrationTests.java
index 778f6536bd57..e28c2657a7c8 100644
--- a/module/spring-boot-amqp/src/dockerTest/java/org/springframework/boot/amqp/testcontainers/SeparateContainersRabbitAndRabbitStreamContainerConnectionDetailsFactoryIntegrationTests.java
+++ b/module/spring-boot-rabbitmq/src/dockerTest/java/org/springframework/boot/rabbitmq/testcontainers/SeparateContainersRabbitAndRabbitStreamContainerConnectionDetailsFactoryIntegrationTests.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.boot.amqp.testcontainers;
+package org.springframework.boot.rabbitmq.testcontainers;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
@@ -35,13 +35,13 @@
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.amqp.autoconfigure.EnvironmentBuilderCustomizer;
-import org.springframework.boot.amqp.autoconfigure.RabbitAutoConfiguration;
-import org.springframework.boot.amqp.autoconfigure.RabbitConnectionDetails;
-import org.springframework.boot.amqp.autoconfigure.RabbitStreamConnectionDetails;
-import org.springframework.boot.amqp.testcontainers.RabbitContainerConnectionDetailsFactory.RabbitMqContainerConnectionDetails;
-import org.springframework.boot.amqp.testcontainers.RabbitStreamContainerConnectionDetailsFactory.RabbitMqStreamContainerConnectionDetails;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
+import org.springframework.boot.rabbitmq.autoconfigure.EnvironmentBuilderCustomizer;
+import org.springframework.boot.rabbitmq.autoconfigure.RabbitAutoConfiguration;
+import org.springframework.boot.rabbitmq.autoconfigure.RabbitConnectionDetails;
+import org.springframework.boot.rabbitmq.autoconfigure.RabbitStreamConnectionDetails;
+import org.springframework.boot.rabbitmq.testcontainers.RabbitContainerConnectionDetailsFactory.RabbitMqContainerConnectionDetails;
+import org.springframework.boot.rabbitmq.testcontainers.RabbitStreamContainerConnectionDetailsFactory.RabbitMqStreamContainerConnectionDetails;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.boot.testsupport.container.TestImage;
import org.springframework.context.annotation.Bean;
diff --git a/module/spring-boot-amqp/src/dockerTest/java/org/springframework/boot/amqp/testcontainers/SingleContainerRabbitAndRabbitStreamContainerConnectionDetailsFactoryIntegrationTests.java b/module/spring-boot-rabbitmq/src/dockerTest/java/org/springframework/boot/rabbitmq/testcontainers/SingleContainerRabbitAndRabbitStreamContainerConnectionDetailsFactoryIntegrationTests.java
similarity index 88%
rename from module/spring-boot-amqp/src/dockerTest/java/org/springframework/boot/amqp/testcontainers/SingleContainerRabbitAndRabbitStreamContainerConnectionDetailsFactoryIntegrationTests.java
rename to module/spring-boot-rabbitmq/src/dockerTest/java/org/springframework/boot/rabbitmq/testcontainers/SingleContainerRabbitAndRabbitStreamContainerConnectionDetailsFactoryIntegrationTests.java
index 6dc8b12291c3..3d306284fa4f 100644
--- a/module/spring-boot-amqp/src/dockerTest/java/org/springframework/boot/amqp/testcontainers/SingleContainerRabbitAndRabbitStreamContainerConnectionDetailsFactoryIntegrationTests.java
+++ b/module/spring-boot-rabbitmq/src/dockerTest/java/org/springframework/boot/rabbitmq/testcontainers/SingleContainerRabbitAndRabbitStreamContainerConnectionDetailsFactoryIntegrationTests.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.boot.amqp.testcontainers;
+package org.springframework.boot.rabbitmq.testcontainers;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
@@ -35,13 +35,13 @@
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.amqp.autoconfigure.EnvironmentBuilderCustomizer;
-import org.springframework.boot.amqp.autoconfigure.RabbitAutoConfiguration;
-import org.springframework.boot.amqp.autoconfigure.RabbitConnectionDetails;
-import org.springframework.boot.amqp.autoconfigure.RabbitStreamConnectionDetails;
-import org.springframework.boot.amqp.testcontainers.RabbitContainerConnectionDetailsFactory.RabbitMqContainerConnectionDetails;
-import org.springframework.boot.amqp.testcontainers.RabbitStreamContainerConnectionDetailsFactory.RabbitMqStreamContainerConnectionDetails;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
+import org.springframework.boot.rabbitmq.autoconfigure.EnvironmentBuilderCustomizer;
+import org.springframework.boot.rabbitmq.autoconfigure.RabbitAutoConfiguration;
+import org.springframework.boot.rabbitmq.autoconfigure.RabbitConnectionDetails;
+import org.springframework.boot.rabbitmq.autoconfigure.RabbitStreamConnectionDetails;
+import org.springframework.boot.rabbitmq.testcontainers.RabbitContainerConnectionDetailsFactory.RabbitMqContainerConnectionDetails;
+import org.springframework.boot.rabbitmq.testcontainers.RabbitStreamContainerConnectionDetailsFactory.RabbitMqStreamContainerConnectionDetails;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.boot.testsupport.container.TestImage;
import org.springframework.context.annotation.Bean;
diff --git a/module/spring-boot-amqp/src/test/resources/logback-test.xml b/module/spring-boot-rabbitmq/src/dockerTest/resources/logback-test.xml
similarity index 100%
rename from module/spring-boot-amqp/src/test/resources/logback-test.xml
rename to module/spring-boot-rabbitmq/src/dockerTest/resources/logback-test.xml
diff --git a/module/spring-boot-amqp/src/dockerTest/resources/org/springframework/boot/amqp/docker/compose/rabbit-and-rabbit-stream-separate-services-compose.yaml b/module/spring-boot-rabbitmq/src/dockerTest/resources/org/springframework/boot/rabbitmq/docker/compose/rabbit-and-rabbit-stream-separate-services-compose.yaml
similarity index 92%
rename from module/spring-boot-amqp/src/dockerTest/resources/org/springframework/boot/amqp/docker/compose/rabbit-and-rabbit-stream-separate-services-compose.yaml
rename to module/spring-boot-rabbitmq/src/dockerTest/resources/org/springframework/boot/rabbitmq/docker/compose/rabbit-and-rabbit-stream-separate-services-compose.yaml
index b6ea102d7bb6..a39fef48210d 100644
--- a/module/spring-boot-amqp/src/dockerTest/resources/org/springframework/boot/amqp/docker/compose/rabbit-and-rabbit-stream-separate-services-compose.yaml
+++ b/module/spring-boot-rabbitmq/src/dockerTest/resources/org/springframework/boot/rabbitmq/docker/compose/rabbit-and-rabbit-stream-separate-services-compose.yaml
@@ -18,4 +18,4 @@ services:
- '5552'
configs:
plugins:
- content: "[rabbitmq_stream]."
+ content: "[rabbitmq_stream]."
\ No newline at end of file
diff --git a/module/spring-boot-amqp/src/dockerTest/resources/org/springframework/boot/amqp/docker/compose/rabbit-and-rabbit-stream-single-service-compose.yaml b/module/spring-boot-rabbitmq/src/dockerTest/resources/org/springframework/boot/rabbitmq/docker/compose/rabbit-and-rabbit-stream-single-service-compose.yaml
similarity index 100%
rename from module/spring-boot-amqp/src/dockerTest/resources/org/springframework/boot/amqp/docker/compose/rabbit-and-rabbit-stream-single-service-compose.yaml
rename to module/spring-boot-rabbitmq/src/dockerTest/resources/org/springframework/boot/rabbitmq/docker/compose/rabbit-and-rabbit-stream-single-service-compose.yaml
diff --git a/module/spring-boot-rabbitmq/src/dockerTest/resources/org/springframework/boot/rabbitmq/docker/compose/rabbit-compose.yaml b/module/spring-boot-rabbitmq/src/dockerTest/resources/org/springframework/boot/rabbitmq/docker/compose/rabbit-compose.yaml
new file mode 100644
index 000000000000..1951fba4bb08
--- /dev/null
+++ b/module/spring-boot-rabbitmq/src/dockerTest/resources/org/springframework/boot/rabbitmq/docker/compose/rabbit-compose.yaml
@@ -0,0 +1,8 @@
+services:
+ rabbitmq:
+ image: '{imageName}'
+ environment:
+ - 'RABBITMQ_DEFAULT_USER=myuser'
+ - 'RABBITMQ_DEFAULT_PASS=secret'
+ ports:
+ - '5672'
diff --git a/module/spring-boot-amqp/src/dockerTest/resources/org/springframework/boot/amqp/docker/compose/rabbit-stream-compose.yaml b/module/spring-boot-rabbitmq/src/dockerTest/resources/org/springframework/boot/rabbitmq/docker/compose/rabbit-stream-compose.yaml
similarity index 100%
rename from module/spring-boot-amqp/src/dockerTest/resources/org/springframework/boot/amqp/docker/compose/rabbit-stream-compose.yaml
rename to module/spring-boot-rabbitmq/src/dockerTest/resources/org/springframework/boot/rabbitmq/docker/compose/rabbit-stream-compose.yaml
diff --git a/module/spring-boot-rabbitmq/src/dockerTest/resources/spring.properties b/module/spring-boot-rabbitmq/src/dockerTest/resources/spring.properties
new file mode 100644
index 000000000000..47dff33f0bb5
--- /dev/null
+++ b/module/spring-boot-rabbitmq/src/dockerTest/resources/spring.properties
@@ -0,0 +1 @@
+spring.test.context.cache.maxSize=1
\ No newline at end of file
diff --git a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/AbstractConnectionFactoryConfigurer.java b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/AbstractConnectionFactoryConfigurer.java
similarity index 98%
rename from module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/AbstractConnectionFactoryConfigurer.java
rename to module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/AbstractConnectionFactoryConfigurer.java
index 07b17ce5a9a1..dd3ae0e53623 100644
--- a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/AbstractConnectionFactoryConfigurer.java
+++ b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/AbstractConnectionFactoryConfigurer.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.boot.amqp.autoconfigure;
+package org.springframework.boot.rabbitmq.autoconfigure;
import java.util.stream.Collectors;
diff --git a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/AbstractRabbitListenerContainerFactoryConfigurer.java b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/AbstractRabbitListenerContainerFactoryConfigurer.java
similarity index 96%
rename from module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/AbstractRabbitListenerContainerFactoryConfigurer.java
rename to module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/AbstractRabbitListenerContainerFactoryConfigurer.java
index ffed69eda93e..9ae7a0ef2cc8 100644
--- a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/AbstractRabbitListenerContainerFactoryConfigurer.java
+++ b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/AbstractRabbitListenerContainerFactoryConfigurer.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.boot.amqp.autoconfigure;
+package org.springframework.boot.rabbitmq.autoconfigure;
import java.util.List;
import java.util.concurrent.Executor;
@@ -28,8 +28,8 @@
import org.springframework.amqp.rabbit.retry.RejectAndDontRequeueRecoverer;
import org.springframework.amqp.rabbit.support.micrometer.RabbitListenerObservationConvention;
import org.springframework.amqp.support.converter.MessageConverter;
-import org.springframework.boot.amqp.autoconfigure.RabbitProperties.ListenerRetry;
-import org.springframework.boot.amqp.autoconfigure.RabbitProperties.Retry;
+import org.springframework.boot.rabbitmq.autoconfigure.RabbitProperties.ListenerRetry;
+import org.springframework.boot.rabbitmq.autoconfigure.RabbitProperties.Retry;
import org.springframework.boot.retry.RetryPolicySettings;
import org.springframework.core.retry.RetryPolicy;
import org.springframework.util.Assert;
diff --git a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/CachingConnectionFactoryConfigurer.java b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/CachingConnectionFactoryConfigurer.java
similarity index 98%
rename from module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/CachingConnectionFactoryConfigurer.java
rename to module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/CachingConnectionFactoryConfigurer.java
index 2221595f78d1..923ba0dd1483 100644
--- a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/CachingConnectionFactoryConfigurer.java
+++ b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/CachingConnectionFactoryConfigurer.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.boot.amqp.autoconfigure;
+package org.springframework.boot.rabbitmq.autoconfigure;
import java.time.Duration;
diff --git a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/ConnectionFactoryCustomizer.java b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/ConnectionFactoryCustomizer.java
similarity index 95%
rename from module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/ConnectionFactoryCustomizer.java
rename to module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/ConnectionFactoryCustomizer.java
index 15f2e14dfff8..229f46fa6b3b 100644
--- a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/ConnectionFactoryCustomizer.java
+++ b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/ConnectionFactoryCustomizer.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.boot.amqp.autoconfigure;
+package org.springframework.boot.rabbitmq.autoconfigure;
import com.rabbitmq.client.ConnectionFactory;
diff --git a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/DirectRabbitListenerContainerFactoryConfigurer.java b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/DirectRabbitListenerContainerFactoryConfigurer.java
similarity index 97%
rename from module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/DirectRabbitListenerContainerFactoryConfigurer.java
rename to module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/DirectRabbitListenerContainerFactoryConfigurer.java
index e4057b5c2ecf..5f467163a189 100644
--- a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/DirectRabbitListenerContainerFactoryConfigurer.java
+++ b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/DirectRabbitListenerContainerFactoryConfigurer.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.boot.amqp.autoconfigure;
+package org.springframework.boot.rabbitmq.autoconfigure;
import org.springframework.amqp.rabbit.config.DirectRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
diff --git a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/EnvironmentBuilderCustomizer.java b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/EnvironmentBuilderCustomizer.java
similarity index 95%
rename from module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/EnvironmentBuilderCustomizer.java
rename to module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/EnvironmentBuilderCustomizer.java
index 8d5f2373cd8e..3bc11bb9d393 100644
--- a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/EnvironmentBuilderCustomizer.java
+++ b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/EnvironmentBuilderCustomizer.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.boot.amqp.autoconfigure;
+package org.springframework.boot.rabbitmq.autoconfigure;
import com.rabbitmq.stream.Environment;
import com.rabbitmq.stream.EnvironmentBuilder;
diff --git a/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/PropertiesRabbitConnectionDetails.java b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/PropertiesRabbitConnectionDetails.java
new file mode 100644
index 000000000000..3e3900f8a475
--- /dev/null
+++ b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/PropertiesRabbitConnectionDetails.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2012-present 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
+ *
+ * https://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.rabbitmq.autoconfigure;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.jspecify.annotations.Nullable;
+
+import org.springframework.boot.rabbitmq.autoconfigure.RabbitProperties.Ssl;
+import org.springframework.boot.ssl.SslBundle;
+import org.springframework.boot.ssl.SslBundles;
+import org.springframework.util.Assert;
+import org.springframework.util.StringUtils;
+
+/**
+ * Adapts {@link RabbitProperties} to {@link RabbitConnectionDetails}.
+ *
+ * @author Moritz Halbritter
+ * @author Andy Wilkinson
+ * @author Phillip Webb
+ */
+class PropertiesRabbitConnectionDetails implements RabbitConnectionDetails {
+
+ private final RabbitProperties properties;
+
+ private final @Nullable SslBundles sslBundles;
+
+ PropertiesRabbitConnectionDetails(RabbitProperties properties, @Nullable SslBundles sslBundles) {
+ this.properties = properties;
+ this.sslBundles = sslBundles;
+ }
+
+ @Override
+ public String getUsername() {
+ return this.properties.determineUsername();
+ }
+
+ @Override
+ public @Nullable String getPassword() {
+ return this.properties.determinePassword();
+ }
+
+ @Override
+ public @Nullable String getVirtualHost() {
+ return this.properties.determineVirtualHost();
+ }
+
+ @Override
+ public List getAddresses() {
+ List addresses = new ArrayList<>();
+ for (String address : this.properties.determineAddresses()) {
+ int portSeparatorIndex = address.lastIndexOf(':');
+ String host = address.substring(0, portSeparatorIndex);
+ String port = address.substring(portSeparatorIndex + 1);
+ addresses.add(new Address(host, Integer.parseInt(port)));
+ }
+ return addresses;
+ }
+
+ @Override
+ public @Nullable SslBundle getSslBundle() {
+ Ssl ssl = this.properties.getSsl();
+ if (!ssl.determineEnabled()) {
+ return null;
+ }
+ if (StringUtils.hasLength(ssl.getBundle())) {
+ Assert.notNull(this.sslBundles, "SSL bundle name has been set but no SSL bundles found in context");
+ return this.sslBundles.getBundle(ssl.getBundle());
+ }
+ return null;
+ }
+
+}
diff --git a/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitAnnotationDrivenConfiguration.java b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitAnnotationDrivenConfiguration.java
new file mode 100644
index 000000000000..a2e01ef3942e
--- /dev/null
+++ b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitAnnotationDrivenConfiguration.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2012-present 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
+ *
+ * https://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.rabbitmq.autoconfigure;
+
+import org.springframework.amqp.rabbit.annotation.EnableRabbit;
+import org.springframework.amqp.rabbit.config.ContainerCustomizer;
+import org.springframework.amqp.rabbit.config.DirectRabbitListenerContainerFactory;
+import org.springframework.amqp.rabbit.config.RabbitListenerConfigUtils;
+import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
+import org.springframework.amqp.rabbit.connection.ConnectionFactory;
+import org.springframework.amqp.rabbit.listener.DirectMessageListenerContainer;
+import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
+import org.springframework.amqp.rabbit.retry.MessageRecoverer;
+import org.springframework.amqp.rabbit.support.micrometer.RabbitListenerObservationConvention;
+import org.springframework.amqp.support.converter.MessageConverter;
+import org.springframework.beans.factory.ObjectProvider;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnThreading;
+import org.springframework.boot.thread.Threading;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.task.VirtualThreadTaskExecutor;
+
+/**
+ * Configuration for Spring AMQP annotation driven endpoints.
+ *
+ * @author Stephane Nicoll
+ * @author Josh Thornhill
+ * @author Moritz Halbritter
+ */
+@Configuration(proxyBeanMethods = false)
+@ConditionalOnClass(EnableRabbit.class)
+class RabbitAnnotationDrivenConfiguration {
+
+ private final ObjectProvider messageConverter;
+
+ private final ObjectProvider messageRecoverer;
+
+ private final ObjectProvider retrySettingsCustomizers;
+
+ private final RabbitProperties properties;
+
+ private final ObjectProvider observationConvention;
+
+ RabbitAnnotationDrivenConfiguration(ObjectProvider messageConverter,
+ ObjectProvider messageRecoverer,
+ ObjectProvider retrySettingsCustomizers,
+ ObjectProvider observationConvention, RabbitProperties properties) {
+ this.messageConverter = messageConverter;
+ this.messageRecoverer = messageRecoverer;
+ this.retrySettingsCustomizers = retrySettingsCustomizers;
+ this.observationConvention = observationConvention;
+ this.properties = properties;
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ @ConditionalOnThreading(Threading.PLATFORM)
+ SimpleRabbitListenerContainerFactoryConfigurer simpleRabbitListenerContainerFactoryConfigurer() {
+ return simpleListenerConfigurer();
+ }
+
+ @Bean(name = "simpleRabbitListenerContainerFactoryConfigurer")
+ @ConditionalOnMissingBean
+ @ConditionalOnThreading(Threading.VIRTUAL)
+ SimpleRabbitListenerContainerFactoryConfigurer simpleRabbitListenerContainerFactoryConfigurerVirtualThreads() {
+ SimpleRabbitListenerContainerFactoryConfigurer configurer = simpleListenerConfigurer();
+ configurer.setTaskExecutor(new VirtualThreadTaskExecutor("rabbit-simple-"));
+ return configurer;
+ }
+
+ @Bean(name = "rabbitListenerContainerFactory")
+ @ConditionalOnMissingBean(name = "rabbitListenerContainerFactory")
+ @ConditionalOnProperty(name = "spring.rabbitmq.listener.type", havingValue = "simple", matchIfMissing = true)
+ SimpleRabbitListenerContainerFactory simpleRabbitListenerContainerFactory(
+ SimpleRabbitListenerContainerFactoryConfigurer configurer, ConnectionFactory connectionFactory,
+ ObjectProvider> simpleContainerCustomizer) {
+ SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
+ configurer.configure(factory, connectionFactory);
+ simpleContainerCustomizer.ifUnique(factory::setContainerCustomizer);
+ return factory;
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ @ConditionalOnThreading(Threading.PLATFORM)
+ DirectRabbitListenerContainerFactoryConfigurer directRabbitListenerContainerFactoryConfigurer() {
+ return directListenerConfigurer();
+ }
+
+ @Bean(name = "directRabbitListenerContainerFactoryConfigurer")
+ @ConditionalOnMissingBean
+ @ConditionalOnThreading(Threading.VIRTUAL)
+ DirectRabbitListenerContainerFactoryConfigurer directRabbitListenerContainerFactoryConfigurerVirtualThreads() {
+ DirectRabbitListenerContainerFactoryConfigurer configurer = directListenerConfigurer();
+ configurer.setTaskExecutor(new VirtualThreadTaskExecutor("rabbit-direct-"));
+ return configurer;
+ }
+
+ @Bean(name = "rabbitListenerContainerFactory")
+ @ConditionalOnMissingBean(name = "rabbitListenerContainerFactory")
+ @ConditionalOnProperty(name = "spring.rabbitmq.listener.type", havingValue = "direct")
+ DirectRabbitListenerContainerFactory directRabbitListenerContainerFactory(
+ DirectRabbitListenerContainerFactoryConfigurer configurer, ConnectionFactory connectionFactory,
+ ObjectProvider> directContainerCustomizer) {
+ DirectRabbitListenerContainerFactory factory = new DirectRabbitListenerContainerFactory();
+ configurer.configure(factory, connectionFactory);
+ directContainerCustomizer.ifUnique(factory::setContainerCustomizer);
+ return factory;
+ }
+
+ private SimpleRabbitListenerContainerFactoryConfigurer simpleListenerConfigurer() {
+ SimpleRabbitListenerContainerFactoryConfigurer configurer = new SimpleRabbitListenerContainerFactoryConfigurer(
+ this.properties);
+ configurer.setMessageConverter(this.messageConverter.getIfUnique());
+ configurer.setMessageRecoverer(this.messageRecoverer.getIfUnique());
+ configurer.setObservationConvention(this.observationConvention.getIfUnique());
+ configurer.setRetrySettingsCustomizers(this.retrySettingsCustomizers.orderedStream().toList());
+ return configurer;
+ }
+
+ private DirectRabbitListenerContainerFactoryConfigurer directListenerConfigurer() {
+ DirectRabbitListenerContainerFactoryConfigurer configurer = new DirectRabbitListenerContainerFactoryConfigurer(
+ this.properties);
+ configurer.setMessageConverter(this.messageConverter.getIfUnique());
+ configurer.setMessageRecoverer(this.messageRecoverer.getIfUnique());
+ configurer.setObservationConvention(this.observationConvention.getIfUnique());
+ configurer.setRetrySettingsCustomizers(this.retrySettingsCustomizers.orderedStream().toList());
+ return configurer;
+ }
+
+ @Configuration(proxyBeanMethods = false)
+ @EnableRabbit
+ @ConditionalOnMissingBean(name = RabbitListenerConfigUtils.RABBIT_LISTENER_ANNOTATION_PROCESSOR_BEAN_NAME)
+ static class EnableRabbitConfiguration {
+
+ }
+
+}
diff --git a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/RabbitAutoConfiguration.java b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitAutoConfiguration.java
similarity index 97%
rename from module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/RabbitAutoConfiguration.java
rename to module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitAutoConfiguration.java
index e6f98bcbd2a8..c023d3eba1ba 100644
--- a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/RabbitAutoConfiguration.java
+++ b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitAutoConfiguration.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.boot.amqp.autoconfigure;
+package org.springframework.boot.rabbitmq.autoconfigure;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.impl.CredentialsProvider;
@@ -72,10 +72,12 @@
* @author Moritz Halbritter
* @author Andy Wilkinson
* @author Scott Frederick
+ * @author Eddú Meléndez
* @since 4.0.0
*/
@AutoConfiguration
@ConditionalOnClass({ RabbitTemplate.class, Channel.class })
+@ConditionalOnMissingBean(type = "org.springframework.amqp.rabbitmq.client.RabbitAmqpTemplate")
@EnableConfigurationProperties(RabbitProperties.class)
@Import({ RabbitAnnotationDrivenConfiguration.class, RabbitStreamConfiguration.class })
public final class RabbitAutoConfiguration {
diff --git a/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitConnectionDetails.java b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitConnectionDetails.java
new file mode 100644
index 000000000000..401cb302eddc
--- /dev/null
+++ b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitConnectionDetails.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2012-present 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
+ *
+ * https://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.rabbitmq.autoconfigure;
+
+import java.util.List;
+
+import org.jspecify.annotations.Nullable;
+
+import org.springframework.boot.autoconfigure.service.connection.ConnectionDetails;
+import org.springframework.boot.ssl.SslBundle;
+import org.springframework.util.Assert;
+
+/**
+ * Details required to establish a connection to a RabbitMQ service.
+ *
+ * @author Moritz Halbritter
+ * @author Andy Wilkinson
+ * @author Phillip Webb
+ * @since 4.0.0
+ */
+public interface RabbitConnectionDetails extends ConnectionDetails {
+
+ /**
+ * Login user to authenticate to the broker.
+ * @return the login user to authenticate to the broker or {@code null}
+ */
+ default @Nullable String getUsername() {
+ return null;
+ }
+
+ /**
+ * Login to authenticate against the broker.
+ * @return the login to authenticate against the broker or {@code null}
+ */
+ default @Nullable String getPassword() {
+ return null;
+ }
+
+ /**
+ * Virtual host to use when connecting to the broker.
+ * @return the virtual host to use when connecting to the broker or {@code null}
+ */
+ default @Nullable String getVirtualHost() {
+ return null;
+ }
+
+ /**
+ * List of addresses to which the client should connect. Must return at least one
+ * address.
+ * @return the list of addresses to which the client should connect
+ */
+ List getAddresses();
+
+ /**
+ * Returns the first address.
+ * @return the first address
+ * @throws IllegalStateException if the address list is empty
+ */
+ default Address getFirstAddress() {
+ List addresses = getAddresses();
+ Assert.state(!addresses.isEmpty(), "Address list is empty");
+ return addresses.get(0);
+ }
+
+ /**
+ * SSL bundle to use.
+ * @return the SSL bundle to use
+ */
+ default @Nullable SslBundle getSslBundle() {
+ return null;
+ }
+
+ /**
+ * A RabbitMQ address.
+ *
+ * @param host the host
+ * @param port the port
+ */
+ record Address(String host, int port) {
+ }
+
+}
diff --git a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/RabbitConnectionFactoryBeanConfigurer.java b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitConnectionFactoryBeanConfigurer.java
similarity index 98%
rename from module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/RabbitConnectionFactoryBeanConfigurer.java
rename to module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitConnectionFactoryBeanConfigurer.java
index de03b57613ca..affee3b6b58c 100644
--- a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/RabbitConnectionFactoryBeanConfigurer.java
+++ b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitConnectionFactoryBeanConfigurer.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.boot.amqp.autoconfigure;
+package org.springframework.boot.rabbitmq.autoconfigure;
import java.time.Duration;
@@ -23,8 +23,8 @@
import org.jspecify.annotations.Nullable;
import org.springframework.amqp.rabbit.connection.RabbitConnectionFactoryBean;
-import org.springframework.boot.amqp.autoconfigure.RabbitConnectionDetails.Address;
import org.springframework.boot.context.properties.PropertyMapper;
+import org.springframework.boot.rabbitmq.autoconfigure.RabbitConnectionDetails.Address;
import org.springframework.boot.ssl.SslBundle;
import org.springframework.boot.ssl.SslBundles;
import org.springframework.core.io.ResourceLoader;
diff --git a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/RabbitListenerRetrySettingsCustomizer.java b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitListenerRetrySettingsCustomizer.java
similarity index 95%
rename from module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/RabbitListenerRetrySettingsCustomizer.java
rename to module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitListenerRetrySettingsCustomizer.java
index 8a3bc26dd23e..50a9232ef978 100644
--- a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/RabbitListenerRetrySettingsCustomizer.java
+++ b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitListenerRetrySettingsCustomizer.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.boot.amqp.autoconfigure;
+package org.springframework.boot.rabbitmq.autoconfigure;
import org.springframework.boot.retry.RetryPolicySettings;
import org.springframework.core.retry.RetryPolicy;
diff --git a/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitProperties.java b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitProperties.java
new file mode 100644
index 000000000000..eca707d04919
--- /dev/null
+++ b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitProperties.java
@@ -0,0 +1,1364 @@
+/*
+ * Copyright 2012-present 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
+ *
+ * https://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.rabbitmq.autoconfigure;
+
+import java.time.Duration;
+import java.time.temporal.ChronoUnit;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.jspecify.annotations.Nullable;
+
+import org.springframework.amqp.core.AcknowledgeMode;
+import org.springframework.amqp.rabbit.connection.AbstractConnectionFactory.AddressShuffleMode;
+import org.springframework.amqp.rabbit.connection.CachingConnectionFactory.CacheMode;
+import org.springframework.amqp.rabbit.connection.CachingConnectionFactory.ConfirmType;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.context.properties.PropertyMapper;
+import org.springframework.boot.context.properties.source.InvalidConfigurationPropertyValueException;
+import org.springframework.boot.convert.DurationUnit;
+import org.springframework.boot.retry.RetryPolicySettings;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.StringUtils;
+import org.springframework.util.unit.DataSize;
+
+/**
+ * Configuration properties for Rabbit.
+ *
+ * @author Greg Turnquist
+ * @author Dave Syer
+ * @author Stephane Nicoll
+ * @author Andy Wilkinson
+ * @author Josh Thornhill
+ * @author Gary Russell
+ * @author Artsiom Yudovin
+ * @author Franjo Zilic
+ * @author Eddú Meléndez
+ * @author Rafael Carvalho
+ * @author Scott Frederick
+ * @author Lasse Wulff
+ * @author Yanming Zhou
+ * @since 4.0.0
+ */
+@ConfigurationProperties("spring.rabbitmq")
+public class RabbitProperties {
+
+ private static final int DEFAULT_PORT = 5672;
+
+ private static final int DEFAULT_PORT_SECURE = 5671;
+
+ private static final int DEFAULT_STREAM_PORT = 5552;
+
+ /**
+ * RabbitMQ host. Ignored if an address is set.
+ */
+ private String host = "localhost";
+
+ /**
+ * RabbitMQ port. Ignored if an address is set. Default to 5672, or 5671 if SSL is
+ * enabled.
+ */
+ private @Nullable Integer port;
+
+ /**
+ * Login user to authenticate to the broker.
+ */
+ private String username = "guest";
+
+ /**
+ * Login to authenticate against the broker.
+ */
+ private String password = "guest";
+
+ /**
+ * SSL configuration.
+ */
+ private final Ssl ssl = new Ssl();
+
+ /**
+ * Virtual host to use when connecting to the broker.
+ */
+ private @Nullable String virtualHost;
+
+ /**
+ * List of addresses to which the client should connect. When set, the host and port
+ * are ignored.
+ */
+ private @Nullable List addresses;
+
+ /**
+ * Mode used to shuffle configured addresses.
+ */
+ private AddressShuffleMode addressShuffleMode = AddressShuffleMode.NONE;
+
+ /**
+ * Requested heartbeat timeout; zero for none. If a duration suffix is not specified,
+ * seconds will be used.
+ */
+ @DurationUnit(ChronoUnit.SECONDS)
+ private @Nullable Duration requestedHeartbeat;
+
+ /**
+ * Number of channels per connection requested by the client. Use 0 for unlimited.
+ */
+ private int requestedChannelMax = 2047;
+
+ /**
+ * Whether to enable publisher returns.
+ */
+ private boolean publisherReturns;
+
+ /**
+ * Type of publisher confirms to use.
+ */
+ private @Nullable ConfirmType publisherConfirmType;
+
+ /**
+ * Connection timeout. Set it to zero to wait forever.
+ */
+ private @Nullable Duration connectionTimeout;
+
+ /**
+ * Continuation timeout for RPC calls in channels. Set it to zero to wait forever.
+ */
+ private Duration channelRpcTimeout = Duration.ofMinutes(10);
+
+ /**
+ * Maximum size of the body of inbound (received) messages.
+ */
+ private DataSize maxInboundMessageBodySize = DataSize.ofMegabytes(64);
+
+ /**
+ * Cache configuration.
+ */
+ private final Cache cache = new Cache();
+
+ /**
+ * Listener container configuration.
+ */
+ private final Listener listener = new Listener();
+
+ private final Template template = new Template();
+
+ private final Stream stream = new Stream();
+
+ private @Nullable List parsedAddresses;
+
+ public String getHost() {
+ return this.host;
+ }
+
+ /**
+ * Returns the host from the first address, or the configured host if no addresses
+ * have been set.
+ * @return the host
+ * @see #setAddresses(List)
+ * @see #getHost()
+ */
+ public String determineHost() {
+ if (CollectionUtils.isEmpty(this.parsedAddresses)) {
+ return getHost();
+ }
+ return this.parsedAddresses.get(0).host;
+ }
+
+ public void setHost(String host) {
+ this.host = host;
+ }
+
+ public @Nullable Integer getPort() {
+ return this.port;
+ }
+
+ /**
+ * Returns the port from the first address, or the configured port if no addresses
+ * have been set.
+ * @return the port
+ * @see #setAddresses(List)
+ * @see #getPort()
+ */
+ public int determinePort() {
+ if (CollectionUtils.isEmpty(this.parsedAddresses)) {
+ Integer port = getPort();
+ if (port != null) {
+ return port;
+ }
+ return Boolean.TRUE.equals(getSsl().getEnabled()) ? DEFAULT_PORT_SECURE : DEFAULT_PORT;
+ }
+ return this.parsedAddresses.get(0).port;
+ }
+
+ public void setPort(@Nullable Integer port) {
+ this.port = port;
+ }
+
+ public @Nullable List getAddresses() {
+ return this.addresses;
+ }
+
+ /**
+ * Returns the configured addresses or a single address ({@code host:port}) created
+ * from the configured host and port if no addresses have been set.
+ * @return the addresses
+ */
+ public List determineAddresses() {
+ if (CollectionUtils.isEmpty(this.parsedAddresses)) {
+ if (this.host.contains(",")) {
+ throw new InvalidConfigurationPropertyValueException("spring.rabbitmq.host", this.host,
+ "Invalid character ','. Value must be a single host. For multiple hosts, use property 'spring.rabbitmq.addresses' instead.");
+ }
+ return List.of(this.host + ":" + determinePort());
+ }
+ List addressStrings = new ArrayList<>();
+ for (Address parsedAddress : this.parsedAddresses) {
+ addressStrings.add(parsedAddress.host + ":" + parsedAddress.port);
+ }
+ return addressStrings;
+ }
+
+ public void setAddresses(List addresses) {
+ this.addresses = addresses;
+ this.parsedAddresses = parseAddresses(addresses);
+ }
+
+ private List parseAddresses(List addresses) {
+ List parsedAddresses = new ArrayList<>();
+ for (String address : addresses) {
+ parsedAddresses.add(new Address(address, Boolean.TRUE.equals(getSsl().getEnabled())));
+ }
+ return parsedAddresses;
+ }
+
+ public String getUsername() {
+ return this.username;
+ }
+
+ /**
+ * If addresses have been set and the first address has a username it is returned.
+ * Otherwise returns the result of calling {@code getUsername()}.
+ * @return the username
+ * @see #setAddresses(List)
+ * @see #getUsername()
+ */
+ public String determineUsername() {
+ if (CollectionUtils.isEmpty(this.parsedAddresses)) {
+ return this.username;
+ }
+ Address address = this.parsedAddresses.get(0);
+ return (address.username != null) ? address.username : this.username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public String getPassword() {
+ return this.password;
+ }
+
+ /**
+ * If addresses have been set and the first address has a password it is returned.
+ * Otherwise returns the result of calling {@code getPassword()}.
+ * @return the password or {@code null}
+ * @see #setAddresses(List)
+ * @see #getPassword()
+ */
+ public @Nullable String determinePassword() {
+ if (CollectionUtils.isEmpty(this.parsedAddresses)) {
+ return getPassword();
+ }
+ Address address = this.parsedAddresses.get(0);
+ return (address.password != null) ? address.password : getPassword();
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public Ssl getSsl() {
+ return this.ssl;
+ }
+
+ public @Nullable String getVirtualHost() {
+ return this.virtualHost;
+ }
+
+ /**
+ * If addresses have been set and the first address has a virtual host it is returned.
+ * Otherwise returns the result of calling {@code getVirtualHost()}.
+ * @return the virtual host or {@code null}
+ * @see #setAddresses(List)
+ * @see #getVirtualHost()
+ */
+ public @Nullable String determineVirtualHost() {
+ if (CollectionUtils.isEmpty(this.parsedAddresses)) {
+ return getVirtualHost();
+ }
+ Address address = this.parsedAddresses.get(0);
+ return (address.virtualHost != null) ? address.virtualHost : getVirtualHost();
+ }
+
+ public void setVirtualHost(@Nullable String virtualHost) {
+ this.virtualHost = StringUtils.hasText(virtualHost) ? virtualHost : "/";
+ }
+
+ public AddressShuffleMode getAddressShuffleMode() {
+ return this.addressShuffleMode;
+ }
+
+ public void setAddressShuffleMode(AddressShuffleMode addressShuffleMode) {
+ this.addressShuffleMode = addressShuffleMode;
+ }
+
+ public @Nullable Duration getRequestedHeartbeat() {
+ return this.requestedHeartbeat;
+ }
+
+ public void setRequestedHeartbeat(@Nullable Duration requestedHeartbeat) {
+ this.requestedHeartbeat = requestedHeartbeat;
+ }
+
+ public int getRequestedChannelMax() {
+ return this.requestedChannelMax;
+ }
+
+ public void setRequestedChannelMax(int requestedChannelMax) {
+ this.requestedChannelMax = requestedChannelMax;
+ }
+
+ public boolean isPublisherReturns() {
+ return this.publisherReturns;
+ }
+
+ public void setPublisherReturns(boolean publisherReturns) {
+ this.publisherReturns = publisherReturns;
+ }
+
+ public @Nullable Duration getConnectionTimeout() {
+ return this.connectionTimeout;
+ }
+
+ public void setPublisherConfirmType(@Nullable ConfirmType publisherConfirmType) {
+ this.publisherConfirmType = publisherConfirmType;
+ }
+
+ public @Nullable ConfirmType getPublisherConfirmType() {
+ return this.publisherConfirmType;
+ }
+
+ public void setConnectionTimeout(@Nullable Duration connectionTimeout) {
+ this.connectionTimeout = connectionTimeout;
+ }
+
+ public Duration getChannelRpcTimeout() {
+ return this.channelRpcTimeout;
+ }
+
+ public void setChannelRpcTimeout(Duration channelRpcTimeout) {
+ this.channelRpcTimeout = channelRpcTimeout;
+ }
+
+ public DataSize getMaxInboundMessageBodySize() {
+ return this.maxInboundMessageBodySize;
+ }
+
+ public void setMaxInboundMessageBodySize(DataSize maxInboundMessageBodySize) {
+ this.maxInboundMessageBodySize = maxInboundMessageBodySize;
+ }
+
+ public Cache getCache() {
+ return this.cache;
+ }
+
+ public Listener getListener() {
+ return this.listener;
+ }
+
+ public Template getTemplate() {
+ return this.template;
+ }
+
+ public Stream getStream() {
+ return this.stream;
+ }
+
+ public class Ssl {
+
+ private static final String SUN_X509 = "SunX509";
+
+ /**
+ * Whether to enable SSL support. Determined automatically if an address is
+ * provided with the protocol (amqp:// vs. amqps://).
+ */
+ private @Nullable Boolean enabled;
+
+ /**
+ * SSL bundle name.
+ */
+ private @Nullable String bundle;
+
+ /**
+ * Path to the key store that holds the SSL certificate.
+ */
+ private @Nullable String keyStore;
+
+ /**
+ * Key store type.
+ */
+ private String keyStoreType = "PKCS12";
+
+ /**
+ * Password used to access the key store.
+ */
+ private @Nullable String keyStorePassword;
+
+ /**
+ * Key store algorithm.
+ */
+ private String keyStoreAlgorithm = SUN_X509;
+
+ /**
+ * Trust store that holds SSL certificates.
+ */
+ private @Nullable String trustStore;
+
+ /**
+ * Trust store type.
+ */
+ private String trustStoreType = "JKS";
+
+ /**
+ * Password used to access the trust store.
+ */
+ private @Nullable String trustStorePassword;
+
+ /**
+ * Trust store algorithm.
+ */
+ private String trustStoreAlgorithm = SUN_X509;
+
+ /**
+ * SSL algorithm to use. By default, configured by the Rabbit client library.
+ */
+ private @Nullable String algorithm;
+
+ /**
+ * Whether to enable server side certificate validation.
+ */
+ private boolean validateServerCertificate = true;
+
+ /**
+ * Whether to enable hostname verification.
+ */
+ private boolean verifyHostname = true;
+
+ public @Nullable Boolean getEnabled() {
+ return this.enabled;
+ }
+
+ /**
+ * Returns whether SSL is enabled from the first address, or the configured ssl
+ * enabled flag if no addresses have been set.
+ * @return whether ssl is enabled
+ * @see #setAddresses(List)
+ * @see #getEnabled() ()
+ */
+ public boolean determineEnabled() {
+ boolean defaultEnabled = Boolean.TRUE.equals(getEnabled()) || this.bundle != null;
+ if (CollectionUtils.isEmpty(RabbitProperties.this.parsedAddresses)) {
+ return defaultEnabled;
+ }
+ Address address = RabbitProperties.this.parsedAddresses.get(0);
+ return address.determineSslEnabled(defaultEnabled);
+ }
+
+ public void setEnabled(@Nullable Boolean enabled) {
+ this.enabled = enabled;
+ }
+
+ public @Nullable String getBundle() {
+ return this.bundle;
+ }
+
+ public void setBundle(@Nullable String bundle) {
+ this.bundle = bundle;
+ }
+
+ public @Nullable String getKeyStore() {
+ return this.keyStore;
+ }
+
+ public void setKeyStore(@Nullable String keyStore) {
+ this.keyStore = keyStore;
+ }
+
+ public String getKeyStoreType() {
+ return this.keyStoreType;
+ }
+
+ public void setKeyStoreType(String keyStoreType) {
+ this.keyStoreType = keyStoreType;
+ }
+
+ public @Nullable String getKeyStorePassword() {
+ return this.keyStorePassword;
+ }
+
+ public void setKeyStorePassword(@Nullable String keyStorePassword) {
+ this.keyStorePassword = keyStorePassword;
+ }
+
+ public String getKeyStoreAlgorithm() {
+ return this.keyStoreAlgorithm;
+ }
+
+ public void setKeyStoreAlgorithm(String keyStoreAlgorithm) {
+ this.keyStoreAlgorithm = keyStoreAlgorithm;
+ }
+
+ public @Nullable String getTrustStore() {
+ return this.trustStore;
+ }
+
+ public void setTrustStore(@Nullable String trustStore) {
+ this.trustStore = trustStore;
+ }
+
+ public String getTrustStoreType() {
+ return this.trustStoreType;
+ }
+
+ public void setTrustStoreType(String trustStoreType) {
+ this.trustStoreType = trustStoreType;
+ }
+
+ public @Nullable String getTrustStorePassword() {
+ return this.trustStorePassword;
+ }
+
+ public void setTrustStorePassword(@Nullable String trustStorePassword) {
+ this.trustStorePassword = trustStorePassword;
+ }
+
+ public String getTrustStoreAlgorithm() {
+ return this.trustStoreAlgorithm;
+ }
+
+ public void setTrustStoreAlgorithm(String trustStoreAlgorithm) {
+ this.trustStoreAlgorithm = trustStoreAlgorithm;
+ }
+
+ public @Nullable String getAlgorithm() {
+ return this.algorithm;
+ }
+
+ public void setAlgorithm(@Nullable String sslAlgorithm) {
+ this.algorithm = sslAlgorithm;
+ }
+
+ public boolean isValidateServerCertificate() {
+ return this.validateServerCertificate;
+ }
+
+ public void setValidateServerCertificate(boolean validateServerCertificate) {
+ this.validateServerCertificate = validateServerCertificate;
+ }
+
+ public boolean isVerifyHostname() {
+ return this.verifyHostname;
+ }
+
+ public void setVerifyHostname(boolean verifyHostname) {
+ this.verifyHostname = verifyHostname;
+ }
+
+ }
+
+ public static class Cache {
+
+ private final Channel channel = new Channel();
+
+ private final Connection connection = new Connection();
+
+ public Channel getChannel() {
+ return this.channel;
+ }
+
+ public Connection getConnection() {
+ return this.connection;
+ }
+
+ public static class Channel {
+
+ /**
+ * Number of channels to retain in the cache. When "check-timeout" > 0, max
+ * channels per connection.
+ */
+ private @Nullable Integer size;
+
+ /**
+ * Duration to wait to obtain a channel if the cache size has been reached. If
+ * 0, always create a new channel.
+ */
+ private @Nullable Duration checkoutTimeout;
+
+ public @Nullable Integer getSize() {
+ return this.size;
+ }
+
+ public void setSize(@Nullable Integer size) {
+ this.size = size;
+ }
+
+ public @Nullable Duration getCheckoutTimeout() {
+ return this.checkoutTimeout;
+ }
+
+ public void setCheckoutTimeout(@Nullable Duration checkoutTimeout) {
+ this.checkoutTimeout = checkoutTimeout;
+ }
+
+ }
+
+ public static class Connection {
+
+ /**
+ * Connection factory cache mode.
+ */
+ private CacheMode mode = CacheMode.CHANNEL;
+
+ /**
+ * Number of connections to cache. Only applies when mode is CONNECTION.
+ */
+ private @Nullable Integer size;
+
+ public CacheMode getMode() {
+ return this.mode;
+ }
+
+ public void setMode(CacheMode mode) {
+ this.mode = mode;
+ }
+
+ public @Nullable Integer getSize() {
+ return this.size;
+ }
+
+ public void setSize(@Nullable Integer size) {
+ this.size = size;
+ }
+
+ }
+
+ }
+
+ public enum ContainerType {
+
+ /**
+ * Container where the RabbitMQ consumer dispatches messages to an invoker thread.
+ */
+ SIMPLE,
+
+ /**
+ * Container where the listener is invoked directly on the RabbitMQ consumer
+ * thread.
+ */
+ DIRECT,
+
+ /**
+ * Container that uses the RabbitMQ Stream Client.
+ */
+ STREAM
+
+ }
+
+ public static class Listener {
+
+ /**
+ * Listener container type.
+ */
+ private ContainerType type = ContainerType.SIMPLE;
+
+ private final SimpleContainer simple = new SimpleContainer();
+
+ private final DirectContainer direct = new DirectContainer();
+
+ private final StreamContainer stream = new StreamContainer();
+
+ public ContainerType getType() {
+ return this.type;
+ }
+
+ public void setType(ContainerType containerType) {
+ this.type = containerType;
+ }
+
+ public SimpleContainer getSimple() {
+ return this.simple;
+ }
+
+ public DirectContainer getDirect() {
+ return this.direct;
+ }
+
+ public StreamContainer getStream() {
+ return this.stream;
+ }
+
+ }
+
+ public abstract static class BaseContainer {
+
+ /**
+ * Whether to enable observation.
+ */
+ private boolean observationEnabled;
+
+ public boolean isObservationEnabled() {
+ return this.observationEnabled;
+ }
+
+ public void setObservationEnabled(boolean observationEnabled) {
+ this.observationEnabled = observationEnabled;
+ }
+
+ }
+
+ public abstract static class AmqpContainer extends BaseContainer {
+
+ /**
+ * Whether to start the container automatically on startup.
+ */
+ private boolean autoStartup = true;
+
+ /**
+ * Acknowledge mode of container.
+ */
+ private @Nullable AcknowledgeMode acknowledgeMode;
+
+ /**
+ * Maximum number of unacknowledged messages that can be outstanding at each
+ * consumer.
+ */
+ private @Nullable Integer prefetch;
+
+ /**
+ * Whether rejected deliveries are re-queued by default.
+ */
+ private @Nullable Boolean defaultRequeueRejected;
+
+ /**
+ * How often idle container events should be published.
+ */
+ private @Nullable Duration idleEventInterval;
+
+ /**
+ * Whether the container should present batched messages as discrete messages or
+ * call the listener with the batch.
+ */
+ private boolean deBatchingEnabled = true;
+
+ /**
+ * Whether the container (when stopped) should stop immediately after processing
+ * the current message or stop after processing all pre-fetched messages.
+ */
+ private boolean forceStop;
+
+ /**
+ * Optional properties for a retry interceptor.
+ */
+ private final ListenerRetry retry = new ListenerRetry();
+
+ public boolean isAutoStartup() {
+ return this.autoStartup;
+ }
+
+ public void setAutoStartup(boolean autoStartup) {
+ this.autoStartup = autoStartup;
+ }
+
+ public @Nullable AcknowledgeMode getAcknowledgeMode() {
+ return this.acknowledgeMode;
+ }
+
+ public void setAcknowledgeMode(@Nullable AcknowledgeMode acknowledgeMode) {
+ this.acknowledgeMode = acknowledgeMode;
+ }
+
+ public @Nullable Integer getPrefetch() {
+ return this.prefetch;
+ }
+
+ public void setPrefetch(@Nullable Integer prefetch) {
+ this.prefetch = prefetch;
+ }
+
+ public @Nullable Boolean getDefaultRequeueRejected() {
+ return this.defaultRequeueRejected;
+ }
+
+ public void setDefaultRequeueRejected(@Nullable Boolean defaultRequeueRejected) {
+ this.defaultRequeueRejected = defaultRequeueRejected;
+ }
+
+ public @Nullable Duration getIdleEventInterval() {
+ return this.idleEventInterval;
+ }
+
+ public void setIdleEventInterval(@Nullable Duration idleEventInterval) {
+ this.idleEventInterval = idleEventInterval;
+ }
+
+ public abstract boolean isMissingQueuesFatal();
+
+ public boolean isDeBatchingEnabled() {
+ return this.deBatchingEnabled;
+ }
+
+ public void setDeBatchingEnabled(boolean deBatchingEnabled) {
+ this.deBatchingEnabled = deBatchingEnabled;
+ }
+
+ public boolean isForceStop() {
+ return this.forceStop;
+ }
+
+ public void setForceStop(boolean forceStop) {
+ this.forceStop = forceStop;
+ }
+
+ public ListenerRetry getRetry() {
+ return this.retry;
+ }
+
+ }
+
+ /**
+ * Configuration properties for {@code SimpleMessageListenerContainer}.
+ */
+ public static class SimpleContainer extends AmqpContainer {
+
+ /**
+ * Minimum number of listener invoker threads.
+ */
+ private @Nullable Integer concurrency;
+
+ /**
+ * Maximum number of listener invoker threads.
+ */
+ private @Nullable Integer maxConcurrency;
+
+ /**
+ * Batch size, expressed as the number of physical messages, to be used by the
+ * container.
+ */
+ private @Nullable Integer batchSize;
+
+ /**
+ * Whether to fail if the queues declared by the container are not available on
+ * the broker and/or whether to stop the container if one or more queues are
+ * deleted at runtime.
+ */
+ private boolean missingQueuesFatal = true;
+
+ /**
+ * Whether the container creates a batch of messages based on the
+ * 'receive-timeout' and 'batch-size'. Coerces 'de-batching-enabled' to true to
+ * include the contents of a producer created batch in the batch as discrete
+ * records.
+ */
+ private boolean consumerBatchEnabled;
+
+ public @Nullable Integer getConcurrency() {
+ return this.concurrency;
+ }
+
+ public void setConcurrency(@Nullable Integer concurrency) {
+ this.concurrency = concurrency;
+ }
+
+ public @Nullable Integer getMaxConcurrency() {
+ return this.maxConcurrency;
+ }
+
+ public void setMaxConcurrency(@Nullable Integer maxConcurrency) {
+ this.maxConcurrency = maxConcurrency;
+ }
+
+ public @Nullable Integer getBatchSize() {
+ return this.batchSize;
+ }
+
+ public void setBatchSize(@Nullable Integer batchSize) {
+ this.batchSize = batchSize;
+ }
+
+ @Override
+ public boolean isMissingQueuesFatal() {
+ return this.missingQueuesFatal;
+ }
+
+ public void setMissingQueuesFatal(boolean missingQueuesFatal) {
+ this.missingQueuesFatal = missingQueuesFatal;
+ }
+
+ public boolean isConsumerBatchEnabled() {
+ return this.consumerBatchEnabled;
+ }
+
+ public void setConsumerBatchEnabled(boolean consumerBatchEnabled) {
+ this.consumerBatchEnabled = consumerBatchEnabled;
+ }
+
+ }
+
+ /**
+ * Configuration properties for {@code DirectMessageListenerContainer}.
+ */
+ public static class DirectContainer extends AmqpContainer {
+
+ /**
+ * Number of consumers per queue.
+ */
+ private @Nullable Integer consumersPerQueue;
+
+ /**
+ * Whether to fail if the queues declared by the container are not available on
+ * the broker.
+ */
+ private boolean missingQueuesFatal;
+
+ public @Nullable Integer getConsumersPerQueue() {
+ return this.consumersPerQueue;
+ }
+
+ public void setConsumersPerQueue(@Nullable Integer consumersPerQueue) {
+ this.consumersPerQueue = consumersPerQueue;
+ }
+
+ @Override
+ public boolean isMissingQueuesFatal() {
+ return this.missingQueuesFatal;
+ }
+
+ public void setMissingQueuesFatal(boolean missingQueuesFatal) {
+ this.missingQueuesFatal = missingQueuesFatal;
+ }
+
+ }
+
+ public static class StreamContainer extends BaseContainer {
+
+ /**
+ * Whether the container will support listeners that consume native stream
+ * messages instead of Spring AMQP messages.
+ */
+ private boolean nativeListener;
+
+ public boolean isNativeListener() {
+ return this.nativeListener;
+ }
+
+ public void setNativeListener(boolean nativeListener) {
+ this.nativeListener = nativeListener;
+ }
+
+ }
+
+ public static class Template {
+
+ private final Retry retry = new Retry();
+
+ /**
+ * Whether to enable mandatory messages.
+ */
+ private @Nullable Boolean mandatory;
+
+ /**
+ * Timeout for receive() operations.
+ */
+ private @Nullable Duration receiveTimeout;
+
+ /**
+ * Timeout for sendAndReceive() operations.
+ */
+ private @Nullable Duration replyTimeout;
+
+ /**
+ * Name of the default exchange to use for send operations.
+ */
+ private String exchange = "";
+
+ /**
+ * Value of a default routing key to use for send operations.
+ */
+ private String routingKey = "";
+
+ /**
+ * Name of the default queue to receive messages from when none is specified
+ * explicitly.
+ */
+ private @Nullable String defaultReceiveQueue;
+
+ /**
+ * Whether to enable observation.
+ */
+ private boolean observationEnabled;
+
+ /**
+ * Simple patterns for allowable packages/classes for deserialization.
+ */
+ private @Nullable List allowedListPatterns;
+
+ public Retry getRetry() {
+ return this.retry;
+ }
+
+ public @Nullable Boolean getMandatory() {
+ return this.mandatory;
+ }
+
+ public void setMandatory(@Nullable Boolean mandatory) {
+ this.mandatory = mandatory;
+ }
+
+ public @Nullable Duration getReceiveTimeout() {
+ return this.receiveTimeout;
+ }
+
+ public void setReceiveTimeout(@Nullable Duration receiveTimeout) {
+ this.receiveTimeout = receiveTimeout;
+ }
+
+ public @Nullable Duration getReplyTimeout() {
+ return this.replyTimeout;
+ }
+
+ public void setReplyTimeout(@Nullable Duration replyTimeout) {
+ this.replyTimeout = replyTimeout;
+ }
+
+ public String getExchange() {
+ return this.exchange;
+ }
+
+ public void setExchange(String exchange) {
+ this.exchange = exchange;
+ }
+
+ public String getRoutingKey() {
+ return this.routingKey;
+ }
+
+ public void setRoutingKey(String routingKey) {
+ this.routingKey = routingKey;
+ }
+
+ public @Nullable String getDefaultReceiveQueue() {
+ return this.defaultReceiveQueue;
+ }
+
+ public void setDefaultReceiveQueue(@Nullable String defaultReceiveQueue) {
+ this.defaultReceiveQueue = defaultReceiveQueue;
+ }
+
+ public boolean isObservationEnabled() {
+ return this.observationEnabled;
+ }
+
+ public void setObservationEnabled(boolean observationEnabled) {
+ this.observationEnabled = observationEnabled;
+ }
+
+ public @Nullable List getAllowedListPatterns() {
+ return this.allowedListPatterns;
+ }
+
+ public void setAllowedListPatterns(@Nullable List allowedListPatterns) {
+ this.allowedListPatterns = allowedListPatterns;
+ }
+
+ }
+
+ public static class Retry {
+
+ /**
+ * Whether publishing retries are enabled.
+ */
+ private boolean enabled;
+
+ /**
+ * Maximum number of retry attempts to deliver a message.
+ */
+ private long maxRetries = 3;
+
+ /**
+ * Duration between the first and second attempt to deliver a message.
+ */
+ private Duration initialInterval = Duration.ofMillis(1000);
+
+ /**
+ * Multiplier to apply to the previous retry interval.
+ */
+ private double multiplier = 1.0;
+
+ /**
+ * Maximum duration between attempts.
+ */
+ private Duration maxInterval = Duration.ofMillis(10000);
+
+ public boolean isEnabled() {
+ return this.enabled;
+ }
+
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ }
+
+ public long getMaxRetries() {
+ return this.maxRetries;
+ }
+
+ public void setMaxRetries(long maxRetries) {
+ this.maxRetries = maxRetries;
+ }
+
+ public Duration getInitialInterval() {
+ return this.initialInterval;
+ }
+
+ public void setInitialInterval(Duration initialInterval) {
+ this.initialInterval = initialInterval;
+ }
+
+ public double getMultiplier() {
+ return this.multiplier;
+ }
+
+ public void setMultiplier(double multiplier) {
+ this.multiplier = multiplier;
+ }
+
+ public Duration getMaxInterval() {
+ return this.maxInterval;
+ }
+
+ public void setMaxInterval(Duration maxInterval) {
+ this.maxInterval = maxInterval;
+ }
+
+ RetryPolicySettings initializeRetryPolicySettings() {
+ PropertyMapper map = PropertyMapper.get();
+ RetryPolicySettings settings = new RetryPolicySettings();
+ map.from(this::getMaxRetries).to(settings::setMaxRetries);
+ map.from(this::getInitialInterval).to(settings::setDelay);
+ map.from(this::getMultiplier).to(settings::setMultiplier);
+ map.from(this::getMaxInterval).to(settings::setMaxDelay);
+ return settings;
+ }
+
+ }
+
+ public static class ListenerRetry extends Retry {
+
+ /**
+ * Whether retries are stateless or stateful.
+ */
+ private boolean stateless = true;
+
+ public boolean isStateless() {
+ return this.stateless;
+ }
+
+ public void setStateless(boolean stateless) {
+ this.stateless = stateless;
+ }
+
+ }
+
+ private static final class Address {
+
+ private static final String PREFIX_AMQP = "amqp://";
+
+ private static final String PREFIX_AMQP_SECURE = "amqps://";
+
+ private String host;
+
+ private int port;
+
+ private @Nullable String username;
+
+ private @Nullable String password;
+
+ private @Nullable String virtualHost;
+
+ private @Nullable Boolean secureConnection;
+
+ private Address(String input, boolean sslEnabled) {
+ input = input.trim();
+ input = trimPrefix(input);
+ input = parseUsernameAndPassword(input);
+ input = parseVirtualHost(input);
+ parseHostAndPort(input, sslEnabled);
+ }
+
+ private String trimPrefix(String input) {
+ if (input.startsWith(PREFIX_AMQP_SECURE)) {
+ this.secureConnection = true;
+ return input.substring(PREFIX_AMQP_SECURE.length());
+ }
+ if (input.startsWith(PREFIX_AMQP)) {
+ this.secureConnection = false;
+ return input.substring(PREFIX_AMQP.length());
+ }
+ return input;
+ }
+
+ private String parseUsernameAndPassword(String input) {
+ String[] splitInput = StringUtils.split(input, "@");
+ if (splitInput == null) {
+ return input;
+ }
+ String credentials = splitInput[0];
+ String[] splitCredentials = StringUtils.split(credentials, ":");
+ if (splitCredentials == null) {
+ this.username = credentials;
+ }
+ else {
+ this.username = splitCredentials[0];
+ this.password = splitCredentials[1];
+ }
+ return splitInput[1];
+ }
+
+ private String parseVirtualHost(String input) {
+ int hostIndex = input.indexOf('/');
+ if (hostIndex >= 0) {
+ this.virtualHost = input.substring(hostIndex + 1);
+ if (this.virtualHost.isEmpty()) {
+ this.virtualHost = "/";
+ }
+ input = input.substring(0, hostIndex);
+ }
+ return input;
+ }
+
+ private void parseHostAndPort(String input, boolean sslEnabled) {
+ int bracketIndex = input.lastIndexOf(']');
+ int colonIndex = input.lastIndexOf(':');
+ if (colonIndex == -1 || colonIndex < bracketIndex) {
+ this.host = input;
+ this.port = (determineSslEnabled(sslEnabled)) ? DEFAULT_PORT_SECURE : DEFAULT_PORT;
+ }
+ else {
+ this.host = input.substring(0, colonIndex);
+ this.port = Integer.parseInt(input.substring(colonIndex + 1));
+ }
+ }
+
+ private boolean determineSslEnabled(boolean sslEnabled) {
+ return (this.secureConnection != null) ? this.secureConnection : sslEnabled;
+ }
+
+ }
+
+ public static final class Stream {
+
+ /**
+ * Host of a RabbitMQ instance with the Stream plugin enabled.
+ */
+ private String host = "localhost";
+
+ /**
+ * Stream port of a RabbitMQ instance with the Stream plugin enabled.
+ */
+ private int port = DEFAULT_STREAM_PORT;
+
+ /**
+ * Virtual host of a RabbitMQ instance with the Stream plugin enabled. When not
+ * set, spring.rabbitmq.virtual-host is used.
+ */
+ private @Nullable String virtualHost;
+
+ /**
+ * Login user to authenticate to the broker. When not set,
+ * spring.rabbitmq.username is used.
+ */
+ private @Nullable String username;
+
+ /**
+ * Login password to authenticate to the broker. When not set
+ * spring.rabbitmq.password is used.
+ */
+ private @Nullable String password;
+
+ /**
+ * Name of the stream.
+ */
+ private @Nullable String name;
+
+ public String getHost() {
+ return this.host;
+ }
+
+ public void setHost(String host) {
+ this.host = host;
+ }
+
+ public int getPort() {
+ return this.port;
+ }
+
+ public void setPort(int port) {
+ this.port = port;
+ }
+
+ public @Nullable String getVirtualHost() {
+ return this.virtualHost;
+ }
+
+ public void setVirtualHost(@Nullable String virtualHost) {
+ this.virtualHost = virtualHost;
+ }
+
+ public @Nullable String getUsername() {
+ return this.username;
+ }
+
+ public void setUsername(@Nullable String username) {
+ this.username = username;
+ }
+
+ public @Nullable String getPassword() {
+ return this.password;
+ }
+
+ public void setPassword(@Nullable String password) {
+ this.password = password;
+ }
+
+ public @Nullable String getName() {
+ return this.name;
+ }
+
+ public void setName(@Nullable String name) {
+ this.name = name;
+ }
+
+ }
+
+}
diff --git a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/RabbitRetryTemplateSettings.java b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitRetryTemplateSettings.java
similarity index 96%
rename from module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/RabbitRetryTemplateSettings.java
rename to module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitRetryTemplateSettings.java
index 8e29c1d440e0..c8c2e7625826 100644
--- a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/RabbitRetryTemplateSettings.java
+++ b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitRetryTemplateSettings.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.boot.amqp.autoconfigure;
+package org.springframework.boot.rabbitmq.autoconfigure;
import java.util.LinkedList;
diff --git a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/RabbitStreamConfiguration.java b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitStreamConfiguration.java
similarity index 97%
rename from module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/RabbitStreamConfiguration.java
rename to module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitStreamConfiguration.java
index 0b396dd01f7e..84e3a2cad7c0 100644
--- a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/RabbitStreamConfiguration.java
+++ b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitStreamConfiguration.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.boot.amqp.autoconfigure;
+package org.springframework.boot.rabbitmq.autoconfigure;
import com.rabbitmq.stream.Environment;
import com.rabbitmq.stream.EnvironmentBuilder;
@@ -23,12 +23,12 @@
import org.springframework.amqp.rabbit.config.ContainerCustomizer;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.beans.factory.ObjectProvider;
-import org.springframework.boot.amqp.autoconfigure.RabbitProperties.Stream;
-import org.springframework.boot.amqp.autoconfigure.RabbitProperties.StreamContainer;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.PropertyMapper;
+import org.springframework.boot.rabbitmq.autoconfigure.RabbitProperties.Stream;
+import org.springframework.boot.rabbitmq.autoconfigure.RabbitProperties.StreamContainer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.rabbit.stream.config.StreamRabbitListenerContainerFactory;
diff --git a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/RabbitStreamConnectionDetails.java b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitStreamConnectionDetails.java
similarity index 96%
rename from module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/RabbitStreamConnectionDetails.java
rename to module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitStreamConnectionDetails.java
index 8b08349167d8..f2fc5bbea1bc 100644
--- a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/RabbitStreamConnectionDetails.java
+++ b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitStreamConnectionDetails.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.boot.amqp.autoconfigure;
+package org.springframework.boot.rabbitmq.autoconfigure;
import org.jspecify.annotations.Nullable;
diff --git a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/RabbitStreamTemplateConfigurer.java b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitStreamTemplateConfigurer.java
similarity index 98%
rename from module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/RabbitStreamTemplateConfigurer.java
rename to module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitStreamTemplateConfigurer.java
index fe7306d3e473..b0a652b8062d 100644
--- a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/RabbitStreamTemplateConfigurer.java
+++ b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitStreamTemplateConfigurer.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.boot.amqp.autoconfigure;
+package org.springframework.boot.rabbitmq.autoconfigure;
import org.jspecify.annotations.Nullable;
diff --git a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/RabbitTemplateConfigurer.java b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitTemplateConfigurer.java
similarity index 99%
rename from module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/RabbitTemplateConfigurer.java
rename to module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitTemplateConfigurer.java
index 52823cb48d9a..a44ac5c73568 100644
--- a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/RabbitTemplateConfigurer.java
+++ b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitTemplateConfigurer.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.boot.amqp.autoconfigure;
+package org.springframework.boot.rabbitmq.autoconfigure;
import java.time.Duration;
import java.util.List;
diff --git a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/RabbitTemplateCustomizer.java b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitTemplateCustomizer.java
similarity index 94%
rename from module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/RabbitTemplateCustomizer.java
rename to module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitTemplateCustomizer.java
index 9015fa8ca49d..eac42c300000 100644
--- a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/RabbitTemplateCustomizer.java
+++ b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitTemplateCustomizer.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.boot.amqp.autoconfigure;
+package org.springframework.boot.rabbitmq.autoconfigure;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
diff --git a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/RabbitTemplateRetrySettingsCustomizer.java b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitTemplateRetrySettingsCustomizer.java
similarity index 95%
rename from module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/RabbitTemplateRetrySettingsCustomizer.java
rename to module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitTemplateRetrySettingsCustomizer.java
index 099b510132bb..7c46996557e0 100644
--- a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/RabbitTemplateRetrySettingsCustomizer.java
+++ b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitTemplateRetrySettingsCustomizer.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.boot.amqp.autoconfigure;
+package org.springframework.boot.rabbitmq.autoconfigure;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.core.retry.RetryTemplate;
diff --git a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/SimpleRabbitListenerContainerFactoryConfigurer.java b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/SimpleRabbitListenerContainerFactoryConfigurer.java
similarity index 97%
rename from module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/SimpleRabbitListenerContainerFactoryConfigurer.java
rename to module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/SimpleRabbitListenerContainerFactoryConfigurer.java
index 10fac5395c1d..34332c70eded 100644
--- a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/SimpleRabbitListenerContainerFactoryConfigurer.java
+++ b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/SimpleRabbitListenerContainerFactoryConfigurer.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.boot.amqp.autoconfigure;
+package org.springframework.boot.rabbitmq.autoconfigure;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
diff --git a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/SslBundleRabbitConnectionFactoryBean.java b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/SslBundleRabbitConnectionFactoryBean.java
similarity index 96%
rename from module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/SslBundleRabbitConnectionFactoryBean.java
rename to module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/SslBundleRabbitConnectionFactoryBean.java
index ae2345fb06bb..da53a2cbe28b 100644
--- a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/SslBundleRabbitConnectionFactoryBean.java
+++ b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/SslBundleRabbitConnectionFactoryBean.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.boot.amqp.autoconfigure;
+package org.springframework.boot.rabbitmq.autoconfigure;
import org.jspecify.annotations.Nullable;
diff --git a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/health/RabbitHealthContributorAutoConfiguration.java b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/health/RabbitHealthContributorAutoConfiguration.java
similarity index 91%
rename from module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/health/RabbitHealthContributorAutoConfiguration.java
rename to module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/health/RabbitHealthContributorAutoConfiguration.java
index 0abccb7e34cf..4bd77803bbc3 100644
--- a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/health/RabbitHealthContributorAutoConfiguration.java
+++ b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/health/RabbitHealthContributorAutoConfiguration.java
@@ -14,12 +14,10 @@
* limitations under the License.
*/
-package org.springframework.boot.amqp.autoconfigure.health;
+package org.springframework.boot.rabbitmq.autoconfigure.health;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
-import org.springframework.boot.amqp.autoconfigure.RabbitAutoConfiguration;
-import org.springframework.boot.amqp.health.RabbitHealthIndicator;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
@@ -28,6 +26,8 @@
import org.springframework.boot.health.autoconfigure.contributor.CompositeHealthContributorConfiguration;
import org.springframework.boot.health.autoconfigure.contributor.ConditionalOnEnabledHealthIndicator;
import org.springframework.boot.health.contributor.HealthContributor;
+import org.springframework.boot.rabbitmq.autoconfigure.RabbitAutoConfiguration;
+import org.springframework.boot.rabbitmq.health.RabbitHealthIndicator;
import org.springframework.context.annotation.Bean;
/**
diff --git a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/health/package-info.java b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/health/package-info.java
similarity index 91%
rename from module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/health/package-info.java
rename to module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/health/package-info.java
index bbd0d5e86d39..27f98c583ad9 100644
--- a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/health/package-info.java
+++ b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/health/package-info.java
@@ -18,6 +18,6 @@
* Auto-configuration for RabbitMQ health.
*/
@NullMarked
-package org.springframework.boot.amqp.autoconfigure.health;
+package org.springframework.boot.rabbitmq.autoconfigure.health;
import org.jspecify.annotations.NullMarked;
diff --git a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/metrics/RabbitConnectionFactoryMetricsPostProcessor.java b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/metrics/RabbitConnectionFactoryMetricsPostProcessor.java
similarity index 96%
rename from module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/metrics/RabbitConnectionFactoryMetricsPostProcessor.java
rename to module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/metrics/RabbitConnectionFactoryMetricsPostProcessor.java
index 9841b953e937..2f9f18802c76 100644
--- a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/metrics/RabbitConnectionFactoryMetricsPostProcessor.java
+++ b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/metrics/RabbitConnectionFactoryMetricsPostProcessor.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.boot.amqp.autoconfigure.metrics;
+package org.springframework.boot.rabbitmq.autoconfigure.metrics;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.MetricsCollector;
@@ -24,7 +24,7 @@
import org.springframework.amqp.rabbit.connection.AbstractConnectionFactory;
import org.springframework.beans.factory.config.BeanPostProcessor;
-import org.springframework.boot.amqp.metrics.RabbitMetrics;
+import org.springframework.boot.rabbitmq.metrics.RabbitMetrics;
import org.springframework.context.ApplicationContext;
import org.springframework.core.Ordered;
import org.springframework.util.StringUtils;
diff --git a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/metrics/RabbitMetricsAutoConfiguration.java b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/metrics/RabbitMetricsAutoConfiguration.java
similarity index 93%
rename from module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/metrics/RabbitMetricsAutoConfiguration.java
rename to module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/metrics/RabbitMetricsAutoConfiguration.java
index 27b5b6ad36ed..2ac68c1396db 100644
--- a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/metrics/RabbitMetricsAutoConfiguration.java
+++ b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/metrics/RabbitMetricsAutoConfiguration.java
@@ -14,17 +14,17 @@
* limitations under the License.
*/
-package org.springframework.boot.amqp.autoconfigure.metrics;
+package org.springframework.boot.rabbitmq.autoconfigure.metrics;
import com.rabbitmq.client.ConnectionFactory;
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.amqp.rabbit.connection.AbstractConnectionFactory;
-import org.springframework.boot.amqp.autoconfigure.RabbitAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.rabbitmq.autoconfigure.RabbitAutoConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
diff --git a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/metrics/package-info.java b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/metrics/package-info.java
similarity index 91%
rename from module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/metrics/package-info.java
rename to module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/metrics/package-info.java
index ab0814c6f728..94b2c885530b 100644
--- a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/metrics/package-info.java
+++ b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/metrics/package-info.java
@@ -18,6 +18,6 @@
* Auto-configuration for RabbitMQ metrics.
*/
@NullMarked
-package org.springframework.boot.amqp.autoconfigure.metrics;
+package org.springframework.boot.rabbitmq.autoconfigure.metrics;
import org.jspecify.annotations.NullMarked;
diff --git a/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/package-info.java b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/package-info.java
new file mode 100644
index 000000000000..8b021e23bb05
--- /dev/null
+++ b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/autoconfigure/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2012-present 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
+ *
+ * https://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.
+ */
+
+/**
+ * Auto-configuration for RabbitMQ.
+ */
+@NullMarked
+package org.springframework.boot.rabbitmq.autoconfigure;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/docker/compose/RabbitDockerComposeConnectionDetailsFactory.java b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/docker/compose/RabbitDockerComposeConnectionDetailsFactory.java
new file mode 100644
index 000000000000..c7a619dc0649
--- /dev/null
+++ b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/docker/compose/RabbitDockerComposeConnectionDetailsFactory.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2012-present 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
+ *
+ * https://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.rabbitmq.docker.compose;
+
+import java.util.List;
+
+import org.jspecify.annotations.Nullable;
+
+import org.springframework.boot.docker.compose.core.RunningService;
+import org.springframework.boot.docker.compose.service.connection.DockerComposeConnectionDetailsFactory;
+import org.springframework.boot.docker.compose.service.connection.DockerComposeConnectionSource;
+import org.springframework.boot.rabbitmq.autoconfigure.RabbitConnectionDetails;
+
+/**
+ * {@link DockerComposeConnectionDetailsFactory} to create {@link RabbitConnectionDetails}
+ * for a {@code rabbitmq} service.
+ *
+ * @author Moritz Halbritter
+ * @author Andy Wilkinson
+ * @author Phillip Webb
+ * @author Scott Frederick
+ */
+class RabbitDockerComposeConnectionDetailsFactory
+ extends DockerComposeConnectionDetailsFactory {
+
+ private static final int RABBITMQ_PORT = 5672;
+
+ protected RabbitDockerComposeConnectionDetailsFactory() {
+ super("rabbitmq");
+ }
+
+ @Override
+ protected @Nullable RabbitConnectionDetails getDockerComposeConnectionDetails(
+ DockerComposeConnectionSource source) {
+ try {
+ return new RabbitDockerComposeConnectionDetails(source.getRunningService());
+ }
+ catch (IllegalStateException ex) {
+ return null;
+ }
+ }
+
+ /**
+ * {@link RabbitConnectionDetails} backed by a {@code rabbitmq}
+ * {@link RunningService}.
+ */
+ static class RabbitDockerComposeConnectionDetails extends DockerComposeConnectionDetails
+ implements RabbitConnectionDetails {
+
+ private final RabbitEnvironment environment;
+
+ private final List addresses;
+
+ protected RabbitDockerComposeConnectionDetails(RunningService service) {
+ super(service);
+ this.environment = new RabbitEnvironment(service.env());
+ this.addresses = List.of(new Address(service.host(), service.ports().get(RABBITMQ_PORT)));
+ }
+
+ @Override
+ public @Nullable String getUsername() {
+ return this.environment.getUsername();
+ }
+
+ @Override
+ public @Nullable String getPassword() {
+ return this.environment.getPassword();
+ }
+
+ @Override
+ public String getVirtualHost() {
+ return "/";
+ }
+
+ @Override
+ public List getAddresses() {
+ return this.addresses;
+ }
+
+ }
+
+}
diff --git a/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/docker/compose/RabbitEnvironment.java b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/docker/compose/RabbitEnvironment.java
new file mode 100644
index 000000000000..1d37579e1a84
--- /dev/null
+++ b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/docker/compose/RabbitEnvironment.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2012-present 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
+ *
+ * https://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.rabbitmq.docker.compose;
+
+import java.util.Map;
+
+import org.jspecify.annotations.Nullable;
+
+/**
+ * RabbitMQ environment details.
+ *
+ * @author Moritz Halbritter
+ * @author Andy Wilkinson
+ * @author Phillip Webb
+ * @author Scott Frederick
+ */
+class RabbitEnvironment {
+
+ private final @Nullable String username;
+
+ private final @Nullable String password;
+
+ RabbitEnvironment(Map env) {
+ this.username = env.getOrDefault("RABBITMQ_DEFAULT_USER", env.getOrDefault("RABBITMQ_USERNAME", "guest"));
+ this.password = env.getOrDefault("RABBITMQ_DEFAULT_PASS", env.getOrDefault("RABBITMQ_PASSWORD", "guest"));
+ }
+
+ @Nullable String getUsername() {
+ return this.username;
+ }
+
+ @Nullable String getPassword() {
+ return this.password;
+ }
+
+}
diff --git a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/docker/compose/RabbitStreamDockerComposeConnectionDetailsFactory.java b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/docker/compose/RabbitStreamDockerComposeConnectionDetailsFactory.java
similarity index 92%
rename from module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/docker/compose/RabbitStreamDockerComposeConnectionDetailsFactory.java
rename to module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/docker/compose/RabbitStreamDockerComposeConnectionDetailsFactory.java
index e482c04c0220..b1f91fcd8a61 100644
--- a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/docker/compose/RabbitStreamDockerComposeConnectionDetailsFactory.java
+++ b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/docker/compose/RabbitStreamDockerComposeConnectionDetailsFactory.java
@@ -14,15 +14,15 @@
* limitations under the License.
*/
-package org.springframework.boot.amqp.docker.compose;
+package org.springframework.boot.rabbitmq.docker.compose;
import org.jspecify.annotations.Nullable;
-import org.springframework.boot.amqp.autoconfigure.RabbitConnectionDetails;
-import org.springframework.boot.amqp.autoconfigure.RabbitStreamConnectionDetails;
import org.springframework.boot.docker.compose.core.RunningService;
import org.springframework.boot.docker.compose.service.connection.DockerComposeConnectionDetailsFactory;
import org.springframework.boot.docker.compose.service.connection.DockerComposeConnectionSource;
+import org.springframework.boot.rabbitmq.autoconfigure.RabbitConnectionDetails;
+import org.springframework.boot.rabbitmq.autoconfigure.RabbitStreamConnectionDetails;
/**
* {@link DockerComposeConnectionDetailsFactory} to create {@link RabbitConnectionDetails}
diff --git a/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/docker/compose/package-info.java b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/docker/compose/package-info.java
new file mode 100644
index 000000000000..7fffb63a7c4c
--- /dev/null
+++ b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/docker/compose/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2012-present 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
+ *
+ * https://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.
+ */
+
+/**
+ * Support for Docker Compose RabbitMQ service connections.
+ */
+@NullMarked
+package org.springframework.boot.rabbitmq.docker.compose;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/health/RabbitHealthIndicator.java b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/health/RabbitHealthIndicator.java
similarity index 97%
rename from module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/health/RabbitHealthIndicator.java
rename to module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/health/RabbitHealthIndicator.java
index 045ab2f89c27..f26777421eb5 100644
--- a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/health/RabbitHealthIndicator.java
+++ b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/health/RabbitHealthIndicator.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.boot.amqp.health;
+package org.springframework.boot.rabbitmq.health;
import org.jspecify.annotations.Nullable;
diff --git a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/health/package-info.java b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/health/package-info.java
similarity index 93%
rename from module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/health/package-info.java
rename to module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/health/package-info.java
index ecb6ea0b1649..83f913732e91 100644
--- a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/health/package-info.java
+++ b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/health/package-info.java
@@ -18,6 +18,6 @@
* Health integration for AMQP and RabbitMQ.
*/
@NullMarked
-package org.springframework.boot.amqp.health;
+package org.springframework.boot.rabbitmq.health;
import org.jspecify.annotations.NullMarked;
diff --git a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/metrics/RabbitMetrics.java b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/metrics/RabbitMetrics.java
similarity index 97%
rename from module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/metrics/RabbitMetrics.java
rename to module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/metrics/RabbitMetrics.java
index 20ae4111b162..1fef99a6ba1d 100644
--- a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/metrics/RabbitMetrics.java
+++ b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/metrics/RabbitMetrics.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.boot.amqp.metrics;
+package org.springframework.boot.rabbitmq.metrics;
import java.util.Collections;
diff --git a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/metrics/package-info.java b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/metrics/package-info.java
similarity index 93%
rename from module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/metrics/package-info.java
rename to module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/metrics/package-info.java
index e63026906cd8..c40e5aed68fc 100644
--- a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/metrics/package-info.java
+++ b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/metrics/package-info.java
@@ -18,6 +18,6 @@
* Metrics for AMQP and RabbitMQ.
*/
@NullMarked
-package org.springframework.boot.amqp.metrics;
+package org.springframework.boot.rabbitmq.metrics;
import org.jspecify.annotations.NullMarked;
diff --git a/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/testcontainers/DeprecatedRabbitContainerConnectionDetailsFactory.java b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/testcontainers/DeprecatedRabbitContainerConnectionDetailsFactory.java
new file mode 100644
index 000000000000..445d8410611a
--- /dev/null
+++ b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/testcontainers/DeprecatedRabbitContainerConnectionDetailsFactory.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2012-present 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
+ *
+ * https://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.rabbitmq.testcontainers;
+
+import java.net.URI;
+import java.util.List;
+
+import org.jspecify.annotations.Nullable;
+import org.testcontainers.containers.RabbitMQContainer;
+
+import org.springframework.boot.rabbitmq.autoconfigure.RabbitConnectionDetails;
+import org.springframework.boot.ssl.SslBundle;
+import org.springframework.boot.testcontainers.service.connection.ContainerConnectionDetailsFactory;
+import org.springframework.boot.testcontainers.service.connection.ContainerConnectionSource;
+import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
+
+/**
+ * {@link ContainerConnectionDetailsFactory} to create {@link RabbitConnectionDetails}
+ * from a {@link ServiceConnection @ServiceConnection}-annotated
+ * {@link RabbitMQContainer}.
+ *
+ * @author Moritz Halbritter
+ * @author Andy Wilkinson
+ * @author Phillip Webb
+ * @deprecated since 4.0.0 for removal in 4.2.0 in favor of
+ * {@link RabbitContainerConnectionDetailsFactory}.
+ */
+@Deprecated(since = "4.0.0", forRemoval = true)
+class DeprecatedRabbitContainerConnectionDetailsFactory
+ extends ContainerConnectionDetailsFactory {
+
+ @Override
+ protected RabbitConnectionDetails getContainerConnectionDetails(
+ ContainerConnectionSource source) {
+ return new RabbitMqContainerConnectionDetails(source);
+ }
+
+ /**
+ * {@link RabbitConnectionDetails} backed by a {@link ContainerConnectionSource}.
+ */
+ private static final class RabbitMqContainerConnectionDetails extends ContainerConnectionDetails
+ implements RabbitConnectionDetails {
+
+ private RabbitMqContainerConnectionDetails(ContainerConnectionSource source) {
+ super(source);
+ }
+
+ @Override
+ public String getUsername() {
+ return getContainer().getAdminUsername();
+ }
+
+ @Override
+ public String getPassword() {
+ return getContainer().getAdminPassword();
+ }
+
+ @Override
+ public List getAddresses() {
+ URI uri = URI.create((getSslBundle() != null) ? getContainer().getAmqpsUrl() : getContainer().getAmqpUrl());
+ return List.of(new Address(uri.getHost(), uri.getPort()));
+ }
+
+ @Override
+ public @Nullable SslBundle getSslBundle() {
+ return super.getSslBundle();
+ }
+
+ }
+
+}
diff --git a/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/testcontainers/RabbitContainerConnectionDetailsFactory.java b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/testcontainers/RabbitContainerConnectionDetailsFactory.java
new file mode 100644
index 000000000000..32a89a3e23ac
--- /dev/null
+++ b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/testcontainers/RabbitContainerConnectionDetailsFactory.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2012-present 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
+ *
+ * https://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.rabbitmq.testcontainers;
+
+import java.net.URI;
+import java.util.List;
+
+import org.jspecify.annotations.Nullable;
+import org.testcontainers.rabbitmq.RabbitMQContainer;
+
+import org.springframework.boot.rabbitmq.autoconfigure.RabbitConnectionDetails;
+import org.springframework.boot.ssl.SslBundle;
+import org.springframework.boot.testcontainers.service.connection.ContainerConnectionDetailsFactory;
+import org.springframework.boot.testcontainers.service.connection.ContainerConnectionSource;
+import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
+
+/**
+ * {@link ContainerConnectionDetailsFactory} to create {@link RabbitConnectionDetails}
+ * from a {@link ServiceConnection @ServiceConnection}-annotated
+ * {@link RabbitMQContainer}.
+ *
+ * @author Moritz Halbritter
+ * @author Andy Wilkinson
+ * @author Phillip Webb
+ */
+class RabbitContainerConnectionDetailsFactory
+ extends ContainerConnectionDetailsFactory {
+
+ @Override
+ protected RabbitConnectionDetails getContainerConnectionDetails(
+ ContainerConnectionSource source) {
+ return new RabbitMqContainerConnectionDetails(source);
+ }
+
+ /**
+ * {@link RabbitConnectionDetails} backed by a {@link ContainerConnectionSource}.
+ */
+ static final class RabbitMqContainerConnectionDetails extends ContainerConnectionDetails
+ implements RabbitConnectionDetails {
+
+ private RabbitMqContainerConnectionDetails(ContainerConnectionSource source) {
+ super(source);
+ }
+
+ @Override
+ public String getUsername() {
+ return getContainer().getAdminUsername();
+ }
+
+ @Override
+ public String getPassword() {
+ return getContainer().getAdminPassword();
+ }
+
+ @Override
+ public List getAddresses() {
+ URI uri = URI.create((getSslBundle() != null) ? getContainer().getAmqpsUrl() : getContainer().getAmqpUrl());
+ return List.of(new Address(uri.getHost(), uri.getPort()));
+ }
+
+ @Override
+ public @Nullable SslBundle getSslBundle() {
+ return super.getSslBundle();
+ }
+
+ }
+
+}
diff --git a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/testcontainers/RabbitStreamContainerConnectionDetailsFactory.java b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/testcontainers/RabbitStreamContainerConnectionDetailsFactory.java
similarity index 95%
rename from module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/testcontainers/RabbitStreamContainerConnectionDetailsFactory.java
rename to module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/testcontainers/RabbitStreamContainerConnectionDetailsFactory.java
index 8d2bf2bc9dc4..6b34cd6fd312 100644
--- a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/testcontainers/RabbitStreamContainerConnectionDetailsFactory.java
+++ b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/testcontainers/RabbitStreamContainerConnectionDetailsFactory.java
@@ -14,11 +14,11 @@
* limitations under the License.
*/
-package org.springframework.boot.amqp.testcontainers;
+package org.springframework.boot.rabbitmq.testcontainers;
import org.testcontainers.rabbitmq.RabbitMQContainer;
-import org.springframework.boot.amqp.autoconfigure.RabbitStreamConnectionDetails;
+import org.springframework.boot.rabbitmq.autoconfigure.RabbitStreamConnectionDetails;
import org.springframework.boot.testcontainers.service.connection.ContainerConnectionDetailsFactory;
import org.springframework.boot.testcontainers.service.connection.ContainerConnectionSource;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
diff --git a/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/testcontainers/package-info.java b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/testcontainers/package-info.java
new file mode 100644
index 000000000000..272d19a6b982
--- /dev/null
+++ b/module/spring-boot-rabbitmq/src/main/java/org/springframework/boot/rabbitmq/testcontainers/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2012-present 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
+ *
+ * https://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.
+ */
+
+/**
+ * Support for testcontainers RabbitMQ service connections.
+ */
+@NullMarked
+package org.springframework.boot.rabbitmq.testcontainers;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/module/spring-boot-amqp/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/module/spring-boot-rabbitmq/src/main/resources/META-INF/additional-spring-configuration-metadata.json
similarity index 100%
rename from module/spring-boot-amqp/src/main/resources/META-INF/additional-spring-configuration-metadata.json
rename to module/spring-boot-rabbitmq/src/main/resources/META-INF/additional-spring-configuration-metadata.json
diff --git a/module/spring-boot-rabbitmq/src/main/resources/META-INF/spring.factories b/module/spring-boot-rabbitmq/src/main/resources/META-INF/spring.factories
new file mode 100644
index 000000000000..aa972952f9cb
--- /dev/null
+++ b/module/spring-boot-rabbitmq/src/main/resources/META-INF/spring.factories
@@ -0,0 +1,7 @@
+# Connection Details Factories
+org.springframework.boot.autoconfigure.service.connection.ConnectionDetailsFactory=\
+org.springframework.boot.rabbitmq.docker.compose.RabbitDockerComposeConnectionDetailsFactory,\
+org.springframework.boot.rabbitmq.docker.compose.RabbitStreamDockerComposeConnectionDetailsFactory,\
+org.springframework.boot.rabbitmq.testcontainers.DeprecatedRabbitContainerConnectionDetailsFactory,\
+org.springframework.boot.rabbitmq.testcontainers.RabbitContainerConnectionDetailsFactory,\
+org.springframework.boot.rabbitmq.testcontainers.RabbitStreamContainerConnectionDetailsFactory
diff --git a/module/spring-boot-rabbitmq/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/module/spring-boot-rabbitmq/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 000000000000..9ec393f97b32
--- /dev/null
+++ b/module/spring-boot-rabbitmq/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1,3 @@
+org.springframework.boot.rabbitmq.autoconfigure.RabbitAutoConfiguration
+org.springframework.boot.rabbitmq.autoconfigure.health.RabbitHealthContributorAutoConfiguration
+org.springframework.boot.rabbitmq.autoconfigure.metrics.RabbitMetricsAutoConfiguration
\ No newline at end of file
diff --git a/module/spring-boot-amqp/src/test/java/org/springframework/boot/amqp/autoconfigure/PropertiesRabbitConnectionDetailsTests.java b/module/spring-boot-rabbitmq/src/test/java/org/springframework/boot/rabbitmq/autoconfigure/PropertiesRabbitConnectionDetailsTests.java
similarity index 95%
rename from module/spring-boot-amqp/src/test/java/org/springframework/boot/amqp/autoconfigure/PropertiesRabbitConnectionDetailsTests.java
rename to module/spring-boot-rabbitmq/src/test/java/org/springframework/boot/rabbitmq/autoconfigure/PropertiesRabbitConnectionDetailsTests.java
index fb37bd6f2712..aed57edc4e04 100644
--- a/module/spring-boot-amqp/src/test/java/org/springframework/boot/amqp/autoconfigure/PropertiesRabbitConnectionDetailsTests.java
+++ b/module/spring-boot-rabbitmq/src/test/java/org/springframework/boot/rabbitmq/autoconfigure/PropertiesRabbitConnectionDetailsTests.java
@@ -14,14 +14,14 @@
* limitations under the License.
*/
-package org.springframework.boot.amqp.autoconfigure;
+package org.springframework.boot.rabbitmq.autoconfigure;
import java.util.List;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
-import org.springframework.boot.amqp.autoconfigure.RabbitConnectionDetails.Address;
+import org.springframework.boot.rabbitmq.autoconfigure.RabbitConnectionDetails.Address;
import org.springframework.boot.ssl.DefaultSslBundleRegistry;
import org.springframework.boot.ssl.SslBundle;
diff --git a/module/spring-boot-amqp/src/test/java/org/springframework/boot/amqp/autoconfigure/RabbitAutoConfigurationTests.java b/module/spring-boot-rabbitmq/src/test/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitAutoConfigurationTests.java
similarity index 99%
rename from module/spring-boot-amqp/src/test/java/org/springframework/boot/amqp/autoconfigure/RabbitAutoConfigurationTests.java
rename to module/spring-boot-rabbitmq/src/test/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitAutoConfigurationTests.java
index 7db86941280d..b25f9cd3c5f9 100644
--- a/module/spring-boot-amqp/src/test/java/org/springframework/boot/amqp/autoconfigure/RabbitAutoConfigurationTests.java
+++ b/module/spring-boot-rabbitmq/src/test/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitAutoConfigurationTests.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.boot.amqp.autoconfigure;
+package org.springframework.boot.rabbitmq.autoconfigure;
import java.security.NoSuchAlgorithmException;
import java.util.Collection;
@@ -942,7 +942,7 @@ void enableSslWithInvalidTrustStoreTypeShouldFail() {
void enableSslWithBundle() {
this.contextRunner.withUserConfiguration(TestConfiguration.class)
.withPropertyValues("spring.rabbitmq.ssl.bundle=test-bundle",
- "spring.ssl.bundle.jks.test-bundle.keystore.location=classpath:org/springframework/boot/amqp/autoconfigure/test.jks",
+ "spring.ssl.bundle.jks.test-bundle.keystore.location=classpath:org/springframework/boot/rabbitmq/autoconfigure/test.jks",
"spring.ssl.bundle.jks.test-bundle.keystore.password=secret")
.run((context) -> {
com.rabbitmq.client.ConnectionFactory rabbitConnectionFactory = getTargetConnectionFactory(context);
@@ -954,9 +954,9 @@ void enableSslWithBundle() {
void enableSslWithKeystoreTypeAndTrustStoreTypeShouldWork() {
this.contextRunner.withUserConfiguration(TestConfiguration.class)
.withPropertyValues("spring.rabbitmq.ssl.enabled:true",
- "spring.rabbitmq.ssl.key-store=/org/springframework/boot/amqp/autoconfigure/test.jks",
+ "spring.rabbitmq.ssl.key-store=/org/springframework/boot/rabbitmq/autoconfigure/test.jks",
"spring.rabbitmq.ssl.key-store-type=jks", "spring.rabbitmq.ssl.key-store-password=secret",
- "spring.rabbitmq.ssl.trust-store=/org/springframework/boot/amqp/autoconfigure/test.jks",
+ "spring.rabbitmq.ssl.trust-store=/org/springframework/boot/rabbitmq/autoconfigure/test.jks",
"spring.rabbitmq.ssl.trust-store-type=jks", "spring.rabbitmq.ssl.trust-store-password=secret")
.run((context) -> assertThat(context).hasNotFailed());
}
@@ -988,10 +988,10 @@ void enableSslWithValidateServerCertificateDefault(CapturedOutput output) {
void enableSslWithValidStoreAlgorithmShouldWork() {
this.contextRunner.withUserConfiguration(TestConfiguration.class)
.withPropertyValues("spring.rabbitmq.ssl.enabled:true",
- "spring.rabbitmq.ssl.key-store=/org/springframework/boot/amqp/autoconfigure/test.jks",
+ "spring.rabbitmq.ssl.key-store=/org/springframework/boot/rabbitmq/autoconfigure/test.jks",
"spring.rabbitmq.ssl.key-store-type=jks", "spring.rabbitmq.ssl.key-store-password=secret",
"spring.rabbitmq.ssl.key-store-algorithm=PKIX",
- "spring.rabbitmq.ssl.trust-store=/org/springframework/boot/amqp/autoconfigure/test.jks",
+ "spring.rabbitmq.ssl.trust-store=/org/springframework/boot/rabbitmq/autoconfigure/test.jks",
"spring.rabbitmq.ssl.trust-store-type=jks", "spring.rabbitmq.ssl.trust-store-password=secret",
"spring.rabbitmq.ssl.trust-store-algorithm=PKIX")
.run((context) -> assertThat(context).hasNotFailed());
@@ -1001,7 +1001,7 @@ void enableSslWithValidStoreAlgorithmShouldWork() {
void enableSslWithInvalidKeyStoreAlgorithmShouldFail() {
this.contextRunner.withUserConfiguration(TestConfiguration.class)
.withPropertyValues("spring.rabbitmq.ssl.enabled:true",
- "spring.rabbitmq.ssl.key-store=/org/springframework/boot/amqp/autoconfigure/test.jks",
+ "spring.rabbitmq.ssl.key-store=/org/springframework/boot/rabbitmq/autoconfigure/test.jks",
"spring.rabbitmq.ssl.key-store-type=jks", "spring.rabbitmq.ssl.key-store-password=secret",
"spring.rabbitmq.ssl.key-store-algorithm=test-invalid-algo")
.run((context) -> {
@@ -1015,7 +1015,7 @@ void enableSslWithInvalidKeyStoreAlgorithmShouldFail() {
void enableSslWithInvalidTrustStoreAlgorithmShouldFail() {
this.contextRunner.withUserConfiguration(TestConfiguration.class)
.withPropertyValues("spring.rabbitmq.ssl.enabled:true",
- "spring.rabbitmq.ssl.trust-store=/org/springframework/boot/amqp/autoconfigure/test.jks",
+ "spring.rabbitmq.ssl.trust-store=/org/springframework/boot/rabbitmq/autoconfigure/test.jks",
"spring.rabbitmq.ssl.trust-store-type=jks", "spring.rabbitmq.ssl.trust-store-password=secret",
"spring.rabbitmq.ssl.trust-store-algorithm=test-invalid-algo")
.run((context) -> {
diff --git a/module/spring-boot-amqp/src/test/java/org/springframework/boot/amqp/autoconfigure/RabbitPropertiesTests.java b/module/spring-boot-rabbitmq/src/test/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitPropertiesTests.java
similarity index 99%
rename from module/spring-boot-amqp/src/test/java/org/springframework/boot/amqp/autoconfigure/RabbitPropertiesTests.java
rename to module/spring-boot-rabbitmq/src/test/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitPropertiesTests.java
index cc3f17a5a802..49cb9ad85147 100644
--- a/module/spring-boot-amqp/src/test/java/org/springframework/boot/amqp/autoconfigure/RabbitPropertiesTests.java
+++ b/module/spring-boot-rabbitmq/src/test/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitPropertiesTests.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.boot.amqp.autoconfigure;
+package org.springframework.boot.rabbitmq.autoconfigure;
import java.util.List;
diff --git a/module/spring-boot-amqp/src/test/java/org/springframework/boot/amqp/autoconfigure/RabbitStreamConfigurationTests.java b/module/spring-boot-rabbitmq/src/test/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitStreamConfigurationTests.java
similarity index 99%
rename from module/spring-boot-amqp/src/test/java/org/springframework/boot/amqp/autoconfigure/RabbitStreamConfigurationTests.java
rename to module/spring-boot-rabbitmq/src/test/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitStreamConfigurationTests.java
index 088c31f6ccdb..87b21eff7e26 100644
--- a/module/spring-boot-amqp/src/test/java/org/springframework/boot/amqp/autoconfigure/RabbitStreamConfigurationTests.java
+++ b/module/spring-boot-rabbitmq/src/test/java/org/springframework/boot/rabbitmq/autoconfigure/RabbitStreamConfigurationTests.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.boot.amqp.autoconfigure;
+package org.springframework.boot.rabbitmq.autoconfigure;
import java.time.Duration;
import java.util.List;
@@ -33,8 +33,8 @@
import org.springframework.amqp.rabbit.listener.RabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.listener.RabbitListenerEndpointRegistry;
import org.springframework.amqp.support.converter.MessageConverter;
-import org.springframework.boot.amqp.autoconfigure.RabbitStreamConfiguration.PropertiesRabbitStreamConnectionDetails;
import org.springframework.boot.autoconfigure.AutoConfigurations;
+import org.springframework.boot.rabbitmq.autoconfigure.RabbitStreamConfiguration.PropertiesRabbitStreamConnectionDetails;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
diff --git a/module/spring-boot-amqp/src/test/java/org/springframework/boot/amqp/autoconfigure/health/RabbitHealthContributorAutoConfigurationTests.java b/module/spring-boot-rabbitmq/src/test/java/org/springframework/boot/rabbitmq/autoconfigure/health/RabbitHealthContributorAutoConfigurationTests.java
similarity index 89%
rename from module/spring-boot-amqp/src/test/java/org/springframework/boot/amqp/autoconfigure/health/RabbitHealthContributorAutoConfigurationTests.java
rename to module/spring-boot-rabbitmq/src/test/java/org/springframework/boot/rabbitmq/autoconfigure/health/RabbitHealthContributorAutoConfigurationTests.java
index 8739399d0aae..4b3571c2c8c6 100644
--- a/module/spring-boot-amqp/src/test/java/org/springframework/boot/amqp/autoconfigure/health/RabbitHealthContributorAutoConfigurationTests.java
+++ b/module/spring-boot-rabbitmq/src/test/java/org/springframework/boot/rabbitmq/autoconfigure/health/RabbitHealthContributorAutoConfigurationTests.java
@@ -14,14 +14,14 @@
* limitations under the License.
*/
-package org.springframework.boot.amqp.autoconfigure.health;
+package org.springframework.boot.rabbitmq.autoconfigure.health;
import org.junit.jupiter.api.Test;
-import org.springframework.boot.amqp.autoconfigure.RabbitAutoConfiguration;
-import org.springframework.boot.amqp.health.RabbitHealthIndicator;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.health.autoconfigure.contributor.HealthContributorAutoConfiguration;
+import org.springframework.boot.rabbitmq.autoconfigure.RabbitAutoConfiguration;
+import org.springframework.boot.rabbitmq.health.RabbitHealthIndicator;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import static org.assertj.core.api.Assertions.assertThat;
diff --git a/module/spring-boot-amqp/src/test/java/org/springframework/boot/amqp/autoconfigure/metrics/RabbitMetricsAutoConfigurationMeterBinderCycleIntegrationTests.java b/module/spring-boot-rabbitmq/src/test/java/org/springframework/boot/rabbitmq/autoconfigure/metrics/RabbitMetricsAutoConfigurationMeterBinderCycleIntegrationTests.java
similarity index 94%
rename from module/spring-boot-amqp/src/test/java/org/springframework/boot/amqp/autoconfigure/metrics/RabbitMetricsAutoConfigurationMeterBinderCycleIntegrationTests.java
rename to module/spring-boot-rabbitmq/src/test/java/org/springframework/boot/rabbitmq/autoconfigure/metrics/RabbitMetricsAutoConfigurationMeterBinderCycleIntegrationTests.java
index 8c8c31a499e0..81928ab80091 100644
--- a/module/spring-boot-amqp/src/test/java/org/springframework/boot/amqp/autoconfigure/metrics/RabbitMetricsAutoConfigurationMeterBinderCycleIntegrationTests.java
+++ b/module/spring-boot-rabbitmq/src/test/java/org/springframework/boot/rabbitmq/autoconfigure/metrics/RabbitMetricsAutoConfigurationMeterBinderCycleIntegrationTests.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.boot.amqp.autoconfigure.metrics;
+package org.springframework.boot.rabbitmq.autoconfigure.metrics;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.binder.MeterBinder;
@@ -22,8 +22,8 @@
import org.junit.jupiter.api.Test;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
-import org.springframework.boot.amqp.autoconfigure.RabbitAutoConfiguration;
import org.springframework.boot.micrometer.metrics.autoconfigure.MetricsAutoConfiguration;
+import org.springframework.boot.rabbitmq.autoconfigure.RabbitAutoConfiguration;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
diff --git a/module/spring-boot-amqp/src/test/java/org/springframework/boot/amqp/autoconfigure/metrics/RabbitMetricsAutoConfigurationTests.java b/module/spring-boot-rabbitmq/src/test/java/org/springframework/boot/rabbitmq/autoconfigure/metrics/RabbitMetricsAutoConfigurationTests.java
similarity index 95%
rename from module/spring-boot-amqp/src/test/java/org/springframework/boot/amqp/autoconfigure/metrics/RabbitMetricsAutoConfigurationTests.java
rename to module/spring-boot-rabbitmq/src/test/java/org/springframework/boot/rabbitmq/autoconfigure/metrics/RabbitMetricsAutoConfigurationTests.java
index b75b0e1857d9..937a1203a096 100644
--- a/module/spring-boot-amqp/src/test/java/org/springframework/boot/amqp/autoconfigure/metrics/RabbitMetricsAutoConfigurationTests.java
+++ b/module/spring-boot-rabbitmq/src/test/java/org/springframework/boot/rabbitmq/autoconfigure/metrics/RabbitMetricsAutoConfigurationTests.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.boot.amqp.autoconfigure.metrics;
+package org.springframework.boot.rabbitmq.autoconfigure.metrics;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
@@ -22,9 +22,9 @@
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
-import org.springframework.boot.amqp.autoconfigure.RabbitAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.micrometer.metrics.autoconfigure.MetricsAutoConfiguration;
+import org.springframework.boot.rabbitmq.autoconfigure.RabbitAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
diff --git a/module/spring-boot-rabbitmq/src/test/java/org/springframework/boot/rabbitmq/docker/compose/RabbitEnvironmentTests.java b/module/spring-boot-rabbitmq/src/test/java/org/springframework/boot/rabbitmq/docker/compose/RabbitEnvironmentTests.java
new file mode 100644
index 000000000000..356d93ad535e
--- /dev/null
+++ b/module/spring-boot-rabbitmq/src/test/java/org/springframework/boot/rabbitmq/docker/compose/RabbitEnvironmentTests.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2012-present 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
+ *
+ * https://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.rabbitmq.docker.compose;
+
+import java.util.Collections;
+import java.util.Map;
+
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link RabbitEnvironment}.
+ *
+ * @author Moritz Halbritter
+ * @author Andy Wilkinson
+ * @author Phillip Webb
+ * @author Scott Frederick
+ */
+class RabbitEnvironmentTests {
+
+ @Test
+ void getUsernameWhenNoRabbitmqDefaultUser() {
+ RabbitEnvironment environment = new RabbitEnvironment(Collections.emptyMap());
+ assertThat(environment.getUsername()).isEqualTo("guest");
+ }
+
+ @Test
+ void getUsernameWhenHasRabbitmqDefaultUser() {
+ RabbitEnvironment environment = new RabbitEnvironment(Map.of("RABBITMQ_DEFAULT_USER", "me"));
+ assertThat(environment.getUsername()).isEqualTo("me");
+ }
+
+ @Test
+ void getUsernameWhenHasRabbitmqUsername() {
+ RabbitEnvironment environment = new RabbitEnvironment(Map.of("RABBITMQ_USERNAME", "me"));
+ assertThat(environment.getUsername()).isEqualTo("me");
+ }
+
+ @Test
+ void getUsernameWhenNoRabbitmqDefaultPass() {
+ RabbitEnvironment environment = new RabbitEnvironment(Collections.emptyMap());
+ assertThat(environment.getPassword()).isEqualTo("guest");
+ }
+
+ @Test
+ void getUsernameWhenHasRabbitmqDefaultPass() {
+ RabbitEnvironment environment = new RabbitEnvironment(Map.of("RABBITMQ_DEFAULT_PASS", "secret"));
+ assertThat(environment.getPassword()).isEqualTo("secret");
+ }
+
+ @Test
+ void getUsernameWhenHasRabbitmqPassword() {
+ RabbitEnvironment environment = new RabbitEnvironment(Map.of("RABBITMQ_PASSWORD", "secret"));
+ assertThat(environment.getPassword()).isEqualTo("secret");
+ }
+
+}
diff --git a/module/spring-boot-amqp/src/test/java/org/springframework/boot/amqp/health/RabbitHealthIndicatorTests.java b/module/spring-boot-rabbitmq/src/test/java/org/springframework/boot/rabbitmq/health/RabbitHealthIndicatorTests.java
similarity index 98%
rename from module/spring-boot-amqp/src/test/java/org/springframework/boot/amqp/health/RabbitHealthIndicatorTests.java
rename to module/spring-boot-rabbitmq/src/test/java/org/springframework/boot/rabbitmq/health/RabbitHealthIndicatorTests.java
index 5ce2f8e64a20..161cb2fa6e94 100644
--- a/module/spring-boot-amqp/src/test/java/org/springframework/boot/amqp/health/RabbitHealthIndicatorTests.java
+++ b/module/spring-boot-rabbitmq/src/test/java/org/springframework/boot/rabbitmq/health/RabbitHealthIndicatorTests.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.boot.amqp.health;
+package org.springframework.boot.rabbitmq.health;
import java.util.Collections;
diff --git a/module/spring-boot-amqp/src/test/java/org/springframework/boot/amqp/metrics/RabbitMetricsTests.java b/module/spring-boot-rabbitmq/src/test/java/org/springframework/boot/rabbitmq/metrics/RabbitMetricsTests.java
similarity index 97%
rename from module/spring-boot-amqp/src/test/java/org/springframework/boot/amqp/metrics/RabbitMetricsTests.java
rename to module/spring-boot-rabbitmq/src/test/java/org/springframework/boot/rabbitmq/metrics/RabbitMetricsTests.java
index 780de803e4f6..a8b3f5b3c1d3 100644
--- a/module/spring-boot-amqp/src/test/java/org/springframework/boot/amqp/metrics/RabbitMetricsTests.java
+++ b/module/spring-boot-rabbitmq/src/test/java/org/springframework/boot/rabbitmq/metrics/RabbitMetricsTests.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.boot.amqp.metrics;
+package org.springframework.boot.rabbitmq.metrics;
import com.rabbitmq.client.ConnectionFactory;
import io.micrometer.core.instrument.Tags;
diff --git a/module/spring-boot-rabbitmq/src/test/resources/logback-test.xml b/module/spring-boot-rabbitmq/src/test/resources/logback-test.xml
new file mode 100644
index 000000000000..b8a41480d7d6
--- /dev/null
+++ b/module/spring-boot-rabbitmq/src/test/resources/logback-test.xml
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/module/spring-boot-amqp/src/test/resources/org/springframework/boot/amqp/autoconfigure/test.jks b/module/spring-boot-rabbitmq/src/test/resources/org/springframework/boot/rabbitmq/autoconfigure/test.jks
similarity index 100%
rename from module/spring-boot-amqp/src/test/resources/org/springframework/boot/amqp/autoconfigure/test.jks
rename to module/spring-boot-rabbitmq/src/test/resources/org/springframework/boot/rabbitmq/autoconfigure/test.jks
diff --git a/settings.gradle b/settings.gradle
index 378bee883abf..bd3bff0d190e 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -163,6 +163,7 @@ include "module:spring-boot-persistence"
include "module:spring-boot-pulsar"
include "module:spring-boot-quartz"
include "module:spring-boot-r2dbc"
+include "module:spring-boot-rabbitmq"
include "module:spring-boot-reactor"
include "module:spring-boot-reactor-netty"
include "module:spring-boot-restclient"
@@ -208,7 +209,6 @@ include "starter:spring-boot-starter-activemq-test"
include "starter:spring-boot-starter-actuator"
include "starter:spring-boot-starter-actuator-test"
include "starter:spring-boot-starter-amqp"
-include "starter:spring-boot-starter-amqp-test"
include "starter:spring-boot-starter-artemis"
include "starter:spring-boot-starter-artemis-test"
include "starter:spring-boot-starter-aspectj"
@@ -322,6 +322,8 @@ include "starter:spring-boot-starter-quartz"
include "starter:spring-boot-starter-quartz-test"
include "starter:spring-boot-starter-r2dbc"
include "starter:spring-boot-starter-r2dbc-test"
+include "starter:spring-boot-starter-rabbitmq"
+include "starter:spring-boot-starter-rabbitmq-test"
include "starter:spring-boot-starter-reactor-netty"
include "starter:spring-boot-starter-restclient"
include "starter:spring-boot-starter-restclient-test"
@@ -436,6 +438,7 @@ include ":smoke-test:spring-boot-smoke-test-prometheus"
include ":smoke-test:spring-boot-smoke-test-property-validation"
include ":smoke-test:spring-boot-smoke-test-pulsar"
include ":smoke-test:spring-boot-smoke-test-quartz"
+include ":smoke-test:spring-boot-smoke-test-rabbitmq"
include ":smoke-test:spring-boot-smoke-test-reactive-oauth2-client"
include ":smoke-test:spring-boot-smoke-test-reactive-oauth2-resource-server"
include ":smoke-test:spring-boot-smoke-test-restclient"
diff --git a/smoke-test/spring-boot-smoke-test-amqp/build.gradle b/smoke-test/spring-boot-smoke-test-amqp/build.gradle
index cadb8379f2ef..b804797cad58 100644
--- a/smoke-test/spring-boot-smoke-test-amqp/build.gradle
+++ b/smoke-test/spring-boot-smoke-test-amqp/build.gradle
@@ -19,13 +19,13 @@ plugins {
id "org.springframework.boot.docker-test"
}
-description = "Spring Boot AMQP smoke test"
+description = "Spring Boot RabbitMQ AMQP smoke test"
dependencies {
implementation(project(":starter:spring-boot-starter-amqp"))
+ dockerTestImplementation(project(":starter:spring-boot-starter-test"))
dockerTestImplementation(project(":core:spring-boot-testcontainers"))
- dockerTestImplementation(project(":starter:spring-boot-starter-amqp-test"))
dockerTestImplementation(project(":test-support:spring-boot-docker-test-support"))
dockerTestImplementation("org.awaitility:awaitility")
dockerTestImplementation("org.testcontainers:testcontainers-junit-jupiter")
@@ -38,4 +38,4 @@ tasks.named("compileTestJava") {
tasks.named("compileDockerTestJava") {
options.nullability.checking = "tests"
-}
+}
\ No newline at end of file
diff --git a/smoke-test/spring-boot-smoke-test-amqp/src/dockerTest/java/smoketest/amqp/SampleRabbitAmqpSimpleApplicationTests.java b/smoke-test/spring-boot-smoke-test-amqp/src/dockerTest/java/smoketest/amqp/SampleRabbitAmqpSimpleApplicationTests.java
new file mode 100644
index 000000000000..bd9f51c562a5
--- /dev/null
+++ b/smoke-test/spring-boot-smoke-test-amqp/src/dockerTest/java/smoketest/amqp/SampleRabbitAmqpSimpleApplicationTests.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2012-present 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
+ *
+ * https://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 smoketest.amqp;
+
+import java.time.Duration;
+
+import org.awaitility.Awaitility;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.testcontainers.junit.jupiter.Container;
+import org.testcontainers.junit.jupiter.Testcontainers;
+import org.testcontainers.rabbitmq.RabbitMQContainer;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.system.CapturedOutput;
+import org.springframework.boot.test.system.OutputCaptureExtension;
+import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
+import org.springframework.boot.testsupport.container.TestImage;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+@SpringBootTest
+@Testcontainers(disabledWithoutDocker = true)
+@ExtendWith(OutputCaptureExtension.class)
+class SampleRabbitAmqpSimpleApplicationTests {
+
+ @Container
+ @ServiceConnection
+ static final RabbitMQContainer rabbit = TestImage.container(RabbitMQContainer.class);
+
+ @Autowired
+ private Sender sender;
+
+ @Test
+ void sendSimpleMessage(CapturedOutput output) {
+ this.sender.send("Test message");
+ Awaitility.waitAtMost(Duration.ofMinutes(1)).untilAsserted(() -> assertThat(output).contains("Test message"));
+ }
+
+}
diff --git a/smoke-test/spring-boot-smoke-test-amqp/src/main/java/smoketest/amqp/SampleRabbitAmqpSimpleApplication.java b/smoke-test/spring-boot-smoke-test-amqp/src/main/java/smoketest/amqp/SampleRabbitAmqpSimpleApplication.java
new file mode 100644
index 000000000000..aff9bc342e3b
--- /dev/null
+++ b/smoke-test/spring-boot-smoke-test-amqp/src/main/java/smoketest/amqp/SampleRabbitAmqpSimpleApplication.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2012-present 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
+ *
+ * https://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 smoketest.amqp;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.springframework.amqp.core.Queue;
+import org.springframework.amqp.rabbit.annotation.RabbitHandler;
+import org.springframework.amqp.rabbit.annotation.RabbitListener;
+import org.springframework.boot.ApplicationRunner;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.messaging.handler.annotation.Payload;
+
+@SpringBootApplication
+@RabbitListener(queues = "foo")
+public class SampleRabbitAmqpSimpleApplication {
+
+ private static final Log logger = LogFactory.getLog(SampleRabbitAmqpSimpleApplication.class);
+
+ @Bean
+ public Sender mySender() {
+ return new Sender();
+ }
+
+ @Bean
+ public Queue fooQueue() {
+ return new Queue("foo");
+ }
+
+ @RabbitHandler
+ public void process(@Payload String foo) {
+ logger.info(foo);
+ }
+
+ @Bean
+ public ApplicationRunner runner(Sender sender) {
+ return (args) -> sender.send("Hello");
+ }
+
+ public static void main(String[] args) {
+ SpringApplication.run(SampleRabbitAmqpSimpleApplication.class, args);
+ }
+
+}
diff --git a/smoke-test/spring-boot-smoke-test-amqp/src/main/java/smoketest/amqp/Sender.java b/smoke-test/spring-boot-smoke-test-amqp/src/main/java/smoketest/amqp/Sender.java
index 078f2416966c..6639bc0316ce 100644
--- a/smoke-test/spring-boot-smoke-test-amqp/src/main/java/smoketest/amqp/Sender.java
+++ b/smoke-test/spring-boot-smoke-test-amqp/src/main/java/smoketest/amqp/Sender.java
@@ -16,16 +16,16 @@
package smoketest.amqp;
-import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.amqp.rabbitmq.client.RabbitAmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
public class Sender {
@Autowired
- private RabbitTemplate rabbitTemplate;
+ private RabbitAmqpTemplate rabbitAmqpTemplate;
public void send(String message) {
- this.rabbitTemplate.convertAndSend("foo", message);
+ this.rabbitAmqpTemplate.convertAndSend("foo", message);
}
}
diff --git a/smoke-test/spring-boot-smoke-test-rabbitmq/build.gradle b/smoke-test/spring-boot-smoke-test-rabbitmq/build.gradle
new file mode 100644
index 000000000000..6da49cf2ee9a
--- /dev/null
+++ b/smoke-test/spring-boot-smoke-test-rabbitmq/build.gradle
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2012-present 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
+ *
+ * https://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.
+ */
+
+plugins {
+ id "java"
+ id "org.springframework.boot.docker-test"
+}
+
+description = "Spring Boot AMQP smoke test"
+
+dependencies {
+ implementation(project(":starter:spring-boot-starter-rabbitmq"))
+
+ dockerTestImplementation(project(":core:spring-boot-testcontainers"))
+ dockerTestImplementation(project(":starter:spring-boot-starter-rabbitmq-test"))
+ dockerTestImplementation(project(":test-support:spring-boot-docker-test-support"))
+ dockerTestImplementation("org.awaitility:awaitility")
+ dockerTestImplementation("org.testcontainers:testcontainers-junit-jupiter")
+ dockerTestImplementation("org.testcontainers:testcontainers-rabbitmq")
+}
+
+tasks.named("compileTestJava") {
+ options.nullability.checking = "tests"
+}
+
+tasks.named("compileDockerTestJava") {
+ options.nullability.checking = "tests"
+}
diff --git a/smoke-test/spring-boot-smoke-test-amqp/src/dockerTest/java/smoketest/amqp/SampleAmqpSimpleApplicationSslTests.java b/smoke-test/spring-boot-smoke-test-rabbitmq/src/dockerTest/java/smoketest/amqp/SampleAmqpSimpleApplicationSslTests.java
similarity index 100%
rename from smoke-test/spring-boot-smoke-test-amqp/src/dockerTest/java/smoketest/amqp/SampleAmqpSimpleApplicationSslTests.java
rename to smoke-test/spring-boot-smoke-test-rabbitmq/src/dockerTest/java/smoketest/amqp/SampleAmqpSimpleApplicationSslTests.java
diff --git a/smoke-test/spring-boot-smoke-test-amqp/src/dockerTest/java/smoketest/amqp/SampleAmqpSimpleApplicationTests.java b/smoke-test/spring-boot-smoke-test-rabbitmq/src/dockerTest/java/smoketest/amqp/SampleAmqpSimpleApplicationTests.java
similarity index 100%
rename from smoke-test/spring-boot-smoke-test-amqp/src/dockerTest/java/smoketest/amqp/SampleAmqpSimpleApplicationTests.java
rename to smoke-test/spring-boot-smoke-test-rabbitmq/src/dockerTest/java/smoketest/amqp/SampleAmqpSimpleApplicationTests.java
diff --git a/smoke-test/spring-boot-smoke-test-amqp/src/dockerTest/java/smoketest/amqp/SecureRabbitMqContainer.java b/smoke-test/spring-boot-smoke-test-rabbitmq/src/dockerTest/java/smoketest/amqp/SecureRabbitMqContainer.java
similarity index 100%
rename from smoke-test/spring-boot-smoke-test-amqp/src/dockerTest/java/smoketest/amqp/SecureRabbitMqContainer.java
rename to smoke-test/spring-boot-smoke-test-rabbitmq/src/dockerTest/java/smoketest/amqp/SecureRabbitMqContainer.java
diff --git a/smoke-test/spring-boot-smoke-test-amqp/src/main/java/smoketest/amqp/SampleAmqpSimpleApplication.java b/smoke-test/spring-boot-smoke-test-rabbitmq/src/main/java/smoketest/amqp/SampleAmqpSimpleApplication.java
similarity index 100%
rename from smoke-test/spring-boot-smoke-test-amqp/src/main/java/smoketest/amqp/SampleAmqpSimpleApplication.java
rename to smoke-test/spring-boot-smoke-test-rabbitmq/src/main/java/smoketest/amqp/SampleAmqpSimpleApplication.java
diff --git a/smoke-test/spring-boot-smoke-test-rabbitmq/src/main/java/smoketest/amqp/Sender.java b/smoke-test/spring-boot-smoke-test-rabbitmq/src/main/java/smoketest/amqp/Sender.java
new file mode 100644
index 000000000000..078f2416966c
--- /dev/null
+++ b/smoke-test/spring-boot-smoke-test-rabbitmq/src/main/java/smoketest/amqp/Sender.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2012-present 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
+ *
+ * https://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 smoketest.amqp;
+
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.beans.factory.annotation.Autowired;
+
+public class Sender {
+
+ @Autowired
+ private RabbitTemplate rabbitTemplate;
+
+ public void send(String message) {
+ this.rabbitTemplate.convertAndSend("foo", message);
+ }
+
+}
diff --git a/smoke-test/spring-boot-smoke-test-rabbitmq/src/main/java/smoketest/amqp/package-info.java b/smoke-test/spring-boot-smoke-test-rabbitmq/src/main/java/smoketest/amqp/package-info.java
new file mode 100644
index 000000000000..bc9e41a079d7
--- /dev/null
+++ b/smoke-test/spring-boot-smoke-test-rabbitmq/src/main/java/smoketest/amqp/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2012-present 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
+ *
+ * https://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.
+ */
+
+@NullMarked
+package smoketest.amqp;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/smoke-test/spring-boot-smoke-test-amqp/src/test/resources/ssl/rabbitmq.conf b/smoke-test/spring-boot-smoke-test-rabbitmq/src/test/resources/ssl/rabbitmq.conf
similarity index 100%
rename from smoke-test/spring-boot-smoke-test-amqp/src/test/resources/ssl/rabbitmq.conf
rename to smoke-test/spring-boot-smoke-test-rabbitmq/src/test/resources/ssl/rabbitmq.conf
diff --git a/smoke-test/spring-boot-smoke-test-amqp/src/test/resources/ssl/test-ca.crt b/smoke-test/spring-boot-smoke-test-rabbitmq/src/test/resources/ssl/test-ca.crt
similarity index 100%
rename from smoke-test/spring-boot-smoke-test-amqp/src/test/resources/ssl/test-ca.crt
rename to smoke-test/spring-boot-smoke-test-rabbitmq/src/test/resources/ssl/test-ca.crt
diff --git a/smoke-test/spring-boot-smoke-test-amqp/src/test/resources/ssl/test-ca.key b/smoke-test/spring-boot-smoke-test-rabbitmq/src/test/resources/ssl/test-ca.key
similarity index 100%
rename from smoke-test/spring-boot-smoke-test-amqp/src/test/resources/ssl/test-ca.key
rename to smoke-test/spring-boot-smoke-test-rabbitmq/src/test/resources/ssl/test-ca.key
diff --git a/smoke-test/spring-boot-smoke-test-amqp/src/test/resources/ssl/test-client.crt b/smoke-test/spring-boot-smoke-test-rabbitmq/src/test/resources/ssl/test-client.crt
similarity index 100%
rename from smoke-test/spring-boot-smoke-test-amqp/src/test/resources/ssl/test-client.crt
rename to smoke-test/spring-boot-smoke-test-rabbitmq/src/test/resources/ssl/test-client.crt
diff --git a/smoke-test/spring-boot-smoke-test-amqp/src/test/resources/ssl/test-client.key b/smoke-test/spring-boot-smoke-test-rabbitmq/src/test/resources/ssl/test-client.key
similarity index 100%
rename from smoke-test/spring-boot-smoke-test-amqp/src/test/resources/ssl/test-client.key
rename to smoke-test/spring-boot-smoke-test-rabbitmq/src/test/resources/ssl/test-client.key
diff --git a/smoke-test/spring-boot-smoke-test-amqp/src/test/resources/ssl/test-server.crt b/smoke-test/spring-boot-smoke-test-rabbitmq/src/test/resources/ssl/test-server.crt
similarity index 100%
rename from smoke-test/spring-boot-smoke-test-amqp/src/test/resources/ssl/test-server.crt
rename to smoke-test/spring-boot-smoke-test-rabbitmq/src/test/resources/ssl/test-server.crt
diff --git a/smoke-test/spring-boot-smoke-test-amqp/src/test/resources/ssl/test-server.key b/smoke-test/spring-boot-smoke-test-rabbitmq/src/test/resources/ssl/test-server.key
similarity index 100%
rename from smoke-test/spring-boot-smoke-test-amqp/src/test/resources/ssl/test-server.key
rename to smoke-test/spring-boot-smoke-test-rabbitmq/src/test/resources/ssl/test-server.key
diff --git a/starter/spring-boot-starter-amqp/build.gradle b/starter/spring-boot-starter-amqp/build.gradle
index bd8d7c906e19..13a1e0d9974c 100644
--- a/starter/spring-boot-starter-amqp/build.gradle
+++ b/starter/spring-boot-starter-amqp/build.gradle
@@ -18,7 +18,7 @@ plugins {
id "org.springframework.boot.starter"
}
-description = "Starter for using Spring AMQP and Rabbit MQ"
+description = "Starter for using Spring AMQP with Rabbit MQ over AMQP 1.0 protocol"
dependencies {
api(project(":starter:spring-boot-starter"))
diff --git a/starter/spring-boot-starter-rabbitmq-test/build.gradle b/starter/spring-boot-starter-rabbitmq-test/build.gradle
new file mode 100644
index 000000000000..1ceffd67e6a4
--- /dev/null
+++ b/starter/spring-boot-starter-rabbitmq-test/build.gradle
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2012-present 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
+ *
+ * https://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.
+ */
+
+plugins {
+ id "org.springframework.boot.starter"
+}
+
+description = "Starter for testing Spring AMQP and Rabbit MQ"
+
+dependencies {
+ api(project(":starter:spring-boot-starter-rabbitmq"))
+ api(project(":starter:spring-boot-starter-test"))
+
+ api("org.springframework.amqp:spring-rabbit-test")
+}
diff --git a/starter/spring-boot-starter-rabbitmq/build.gradle b/starter/spring-boot-starter-rabbitmq/build.gradle
new file mode 100644
index 000000000000..2069eb480971
--- /dev/null
+++ b/starter/spring-boot-starter-rabbitmq/build.gradle
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2012-present 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
+ *
+ * https://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.
+ */
+
+plugins {
+ id "org.springframework.boot.starter"
+}
+
+description = "Starter for using Spring AMQP with Rabbit MQ over AMQP 0.9.1 protocol"
+
+dependencies {
+ api(project(":starter:spring-boot-starter"))
+
+ api(project(":module:spring-boot-rabbitmq"))
+
+ api("org.springframework.amqp:spring-rabbit")
+}
diff --git a/test-support/spring-boot-docker-test-support/src/main/java/org/springframework/boot/testsupport/container/TestImage.java b/test-support/spring-boot-docker-test-support/src/main/java/org/springframework/boot/testsupport/container/TestImage.java
index e64fc32615cf..67b52a1fa2be 100644
--- a/test-support/spring-boot-docker-test-support/src/main/java/org/springframework/boot/testsupport/container/TestImage.java
+++ b/test-support/spring-boot-docker-test-support/src/main/java/org/springframework/boot/testsupport/container/TestImage.java
@@ -247,7 +247,7 @@ public enum TestImage {
/**
* A container image suitable for testing RabbitMQ.
*/
- RABBITMQ("rabbitmq", "3.11-alpine", () -> RabbitMQContainer.class,
+ RABBITMQ("rabbitmq", "4.2.4-alpine", () -> RabbitMQContainer.class,
(container) -> ((RabbitMQContainer) container).withStartupTimeout(Duration.ofMinutes(4))),
/**