Browse Source

Polish spring amqp properties

Signed-off-by: Eddú Meléndez <eddu.melendez@gmail.com>
Eddú Meléndez 3 weeks ago
parent
commit
cec40bb8d4
No known key found for this signature in database
  1. 2
      documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/features/dev-services.adoc
  2. 13
      module/spring-boot-amqp/src/dockerTest/java/org/springframework/boot/amqp/docker/compose/RabbitDockerComposeConnectionDetailsFactoryIntegrationTests.java
  3. 5
      module/spring-boot-amqp/src/dockerTest/java/org/springframework/boot/amqp/testcontainers/RabbitContainerConnectionDetailsFactoryIntegrationTests.java
  4. 39
      module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/AmqpConnectionDetails.java
  5. 383
      module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/AmqpProperties.java
  6. 58
      module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/PropertiesAmqpConnectionDetails.java
  7. 88
      module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/PropertiesRabbitConnectionDetails.java
  8. 21
      module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/RabbitAmqpAutoConfiguration.java
  9. 1364
      module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/RabbitProperties.java
  10. 33
      module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/docker/compose/RabbitDockerComposeConnectionDetailsFactory.java
  11. 85
      module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/testcontainers/DeprecatedRabbitContainerConnectionDetailsFactory.java
  12. 31
      module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/testcontainers/RabbitContainerConnectionDetailsFactory.java

2
documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/features/dev-services.adoc

@ -125,7 +125,7 @@ The following service connections are currently supported:
| javadoc:org.springframework.boot.r2dbc.autoconfigure.R2dbcConnectionDetails[] | javadoc:org.springframework.boot.r2dbc.autoconfigure.R2dbcConnectionDetails[]
| Containers named "clickhouse/clickhouse-server", "gvenzl/oracle-free", "gvenzl/oracle-xe", "mariadb", "mssql/server", "mysql", or "postgres" | Containers named "clickhouse/clickhouse-server", "gvenzl/oracle-free", "gvenzl/oracle-xe", "mariadb", "mssql/server", "mysql", or "postgres"
| javadoc:org.springframework.boot.amqp.autoconfigure.RabbitConnectionDetails[] | javadoc:org.springframework.boot.amqp.autoconfigure.AmqpConnectionDetails[]
| Containers named "rabbitmq" | Containers named "rabbitmq"
| javadoc:org.springframework.boot.rabbitmq.autoconfigure.RabbitConnectionDetails[] | javadoc:org.springframework.boot.rabbitmq.autoconfigure.RabbitConnectionDetails[]

13
module/spring-boot-amqp/src/dockerTest/java/org/springframework/boot/amqp/docker/compose/RabbitDockerComposeConnectionDetailsFactoryIntegrationTests.java

@ -16,8 +16,8 @@
package org.springframework.boot.amqp.docker.compose; package org.springframework.boot.amqp.docker.compose;
import org.springframework.boot.amqp.autoconfigure.RabbitConnectionDetails; import org.springframework.boot.amqp.autoconfigure.AmqpConnectionDetails;
import org.springframework.boot.amqp.autoconfigure.RabbitConnectionDetails.Address; import org.springframework.boot.amqp.autoconfigure.AmqpConnectionDetails.Address;
import org.springframework.boot.docker.compose.service.connection.test.DockerComposeTest; import org.springframework.boot.docker.compose.service.connection.test.DockerComposeTest;
import org.springframework.boot.testsupport.container.TestImage; import org.springframework.boot.testsupport.container.TestImage;
@ -30,20 +30,21 @@ import static org.assertj.core.api.Assertions.assertThat;
* @author Andy Wilkinson * @author Andy Wilkinson
* @author Phillip Webb * @author Phillip Webb
* @author Scott Frederick * @author Scott Frederick
* @author Eddú Meléndez
*/ */
class RabbitDockerComposeConnectionDetailsFactoryIntegrationTests { class RabbitDockerComposeConnectionDetailsFactoryIntegrationTests {
@DockerComposeTest(composeFile = "rabbit-compose.yaml", image = TestImage.RABBITMQ) @DockerComposeTest(composeFile = "rabbit-compose.yaml", image = TestImage.RABBITMQ)
void runCreatesConnectionDetails(RabbitConnectionDetails connectionDetails) { void runCreatesConnectionDetails(AmqpConnectionDetails connectionDetails) {
assertConnectionDetails(connectionDetails); assertConnectionDetails(connectionDetails);
} }
private void assertConnectionDetails(RabbitConnectionDetails connectionDetails) { private void assertConnectionDetails(AmqpConnectionDetails connectionDetails) {
assertThat(connectionDetails.getUsername()).isEqualTo("myuser"); assertThat(connectionDetails.getUsername()).isEqualTo("myuser");
assertThat(connectionDetails.getPassword()).isEqualTo("secret"); assertThat(connectionDetails.getPassword()).isEqualTo("secret");
assertThat(connectionDetails.getVirtualHost()).isEqualTo("/"); assertThat(connectionDetails.getVirtualHost()).isEqualTo("/");
assertThat(connectionDetails.getAddresses()).hasSize(1); assertThat(connectionDetails.getAddress()).isNotNull();
Address address = connectionDetails.getFirstAddress(); Address address = connectionDetails.getAddress();
assertThat(address.host()).isNotNull(); assertThat(address.host()).isNotNull();
assertThat(address.port()).isGreaterThan(0); assertThat(address.port()).isGreaterThan(0);
} }

5
module/spring-boot-amqp/src/dockerTest/java/org/springframework/boot/amqp/testcontainers/RabbitContainerConnectionDetailsFactoryIntegrationTests.java

@ -30,8 +30,8 @@ import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbitmq.client.RabbitAmqpTemplate; import org.springframework.amqp.rabbitmq.client.RabbitAmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.amqp.autoconfigure.AmqpConnectionDetails;
import org.springframework.boot.amqp.autoconfigure.RabbitAmqpAutoConfiguration; import org.springframework.boot.amqp.autoconfigure.RabbitAmqpAutoConfiguration;
import org.springframework.boot.amqp.autoconfigure.RabbitConnectionDetails;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration; import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection; import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.boot.testsupport.container.TestImage; import org.springframework.boot.testsupport.container.TestImage;
@ -47,6 +47,7 @@ import static org.assertj.core.api.Assertions.assertThat;
* @author Moritz Halbritter * @author Moritz Halbritter
* @author Andy Wilkinson * @author Andy Wilkinson
* @author Phillip Webb * @author Phillip Webb
* @author Eddú Meléndez
*/ */
@SpringJUnitConfig @SpringJUnitConfig
@Testcontainers(disabledWithoutDocker = true) @Testcontainers(disabledWithoutDocker = true)
@ -57,7 +58,7 @@ class RabbitContainerConnectionDetailsFactoryIntegrationTests {
static final RabbitMQContainer rabbit = TestImage.container(RabbitMQContainer.class); static final RabbitMQContainer rabbit = TestImage.container(RabbitMQContainer.class);
@Autowired(required = false) @Autowired(required = false)
private RabbitConnectionDetails connectionDetails; private AmqpConnectionDetails connectionDetails;
@Autowired @Autowired
private RabbitAmqpTemplate rabbitAmqpTemplate; private RabbitAmqpTemplate rabbitAmqpTemplate;

39
module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/RabbitConnectionDetails.java → module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/AmqpConnectionDetails.java

@ -16,23 +16,17 @@
package org.springframework.boot.amqp.autoconfigure; package org.springframework.boot.amqp.autoconfigure;
import java.util.List;
import org.jspecify.annotations.Nullable; import org.jspecify.annotations.Nullable;
import org.springframework.boot.autoconfigure.service.connection.ConnectionDetails; 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. * Details required to establish a connection to a RabbitMQ AMQP service.
* *
* @author Moritz Halbritter * @author Eddú Meléndez
* @author Andy Wilkinson * @since 4.1.0
* @author Phillip Webb
* @since 4.0.0
*/ */
public interface RabbitConnectionDetails extends ConnectionDetails { public interface AmqpConnectionDetails extends ConnectionDetails {
/** /**
* Login user to authenticate to the broker. * Login user to authenticate to the broker.
@ -59,30 +53,11 @@ public interface RabbitConnectionDetails extends ConnectionDetails {
} }
/** /**
* List of addresses to which the client should connect. Must return at least one * Returns the address.
* address. * @return the address
* @return the list of addresses to which the client should connect
*/
List<Address> getAddresses();
/**
* Returns the first address.
* @return the first address
* @throws IllegalStateException if the address list is empty * @throws IllegalStateException if the address list is empty
*/ */
default Address getFirstAddress() { Address getAddress();
List<Address> 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. * A RabbitMQ address.

383
module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/AmqpProperties.java

@ -0,0 +1,383 @@
/*
* 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.jspecify.annotations.Nullable;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.source.InvalidConfigurationPropertyValueException;
import org.springframework.util.StringUtils;
/**
* Configuration properties for Rabbit AMQP.
*
* @author Eddú Meléndez
* @since 4.1.0
*/
@ConfigurationProperties("spring.amqp")
public class AmqpProperties {
private static final int DEFAULT_PORT = 5672;
/**
* 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";
/**
* Virtual host to use when connecting to the broker.
*/
private @Nullable String virtualHost;
/**
* The address to which the client should connect. When set, the host and port are
* ignored.
*/
private @Nullable String address;
/**
* Listener container configuration.
*/
private final Listener listener = new Listener();
private final Template template = new Template();
private @Nullable Address parsedAddress;
public String getHost() {
return this.host;
}
public void setHost(String host) {
this.host = host;
}
public @Nullable Integer getPort() {
return this.port;
}
/**
* Returns the port from the address, or the configured port if no address have been
* set.
* @return the port
* @see #setAddress(String)
* @see #getPort()
*/
public int determinePort() {
if (this.parsedAddress == null) {
Integer port = getPort();
if (port != null) {
return port;
}
return DEFAULT_PORT;
}
return this.parsedAddress.port;
}
public void setPort(@Nullable Integer port) {
this.port = port;
}
public @Nullable String getAddress() {
return this.address;
}
/**
* Returns the configured address ({@code host:port}) created from the configured host
* and port.
* @return the address
*/
public String determineAddress() {
if (this.parsedAddress == null) {
if (this.host.contains(",")) {
throw new InvalidConfigurationPropertyValueException("spring.amqp.host", this.host,
"Invalid character ','. Value must be a single host. For multiple hosts, use property 'spring.amqp.address' instead.");
}
return this.host + ":" + determinePort();
}
return this.parsedAddress.host + ":" + this.parsedAddress.port;
}
public void setAddress(String address) {
this.address = address;
this.parsedAddress = parseAddress(address);
}
private Address parseAddress(String address) {
return new Address(address);
}
public String getUsername() {
return this.username;
}
/**
* If address has been set and has a username it is returned. Otherwise returns the
* result of calling {@code getUsername()}.
* @return the username
* @see #setAddress(String)
* @see #getUsername()
*/
public String determineUsername() {
if (this.parsedAddress == null) {
return this.username;
}
Address address = this.parsedAddress;
return (address.username != null) ? address.username : this.username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return this.password;
}
/**
* If address has been set and has a password it is returned. Otherwise returns the
* result of calling {@code getPassword()}.
* @return the password or {@code null}
* @see #setAddress(String)
* @see #getPassword()
*/
public @Nullable String determinePassword() {
if (this.parsedAddress == null) {
return getPassword();
}
Address address = this.parsedAddress;
return (address.password != null) ? address.password : getPassword();
}
public void setPassword(String password) {
this.password = password;
}
public @Nullable String getVirtualHost() {
return this.virtualHost;
}
/**
* If address has been set and has a virtual host it is returned. Otherwise returns
* the result of calling {@code getVirtualHost()}.
* @return the virtual host or {@code null}
* @see #setAddress(String)
* @see #getVirtualHost()
*/
public @Nullable String determineVirtualHost() {
if (this.parsedAddress == null) {
return getVirtualHost();
}
Address address = this.parsedAddress;
return (address.virtualHost != null) ? address.virtualHost : getVirtualHost();
}
public void setVirtualHost(@Nullable String virtualHost) {
this.virtualHost = StringUtils.hasText(virtualHost) ? virtualHost : "/";
}
public Listener getListener() {
return this.listener;
}
public Template getTemplate() {
return this.template;
}
public static class Listener {
private final AmqpContainer amqp = new AmqpContainer();
public AmqpContainer getAmqp() {
return this.amqp;
}
}
/**
* Configuration properties for {@code RabbitAmqpListenerContainer}.
*/
public static class AmqpContainer {
/**
* Whether to enable observation.
*/
private boolean observationEnabled;
/**
* Batch size, expressed as the number of physical messages, to be used by the
* container.
*/
private @Nullable Integer batchSize;
public boolean isObservationEnabled() {
return this.observationEnabled;
}
public void setObservationEnabled(boolean observationEnabled) {
this.observationEnabled = observationEnabled;
}
public @Nullable Integer getBatchSize() {
return this.batchSize;
}
public void setBatchSize(@Nullable Integer batchSize) {
this.batchSize = batchSize;
}
}
public static class Template {
/**
* 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;
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;
}
}
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 Address(String input) {
input = input.trim();
input = trimPrefix(input);
input = parseUsernameAndPassword(input);
input = parseVirtualHost(input);
parseHostAndPort(input);
}
private String trimPrefix(String input) {
if (input.startsWith(PREFIX_AMQP_SECURE)) {
return input.substring(PREFIX_AMQP_SECURE.length());
}
if (input.startsWith(PREFIX_AMQP)) {
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) {
int bracketIndex = input.lastIndexOf(']');
int colonIndex = input.lastIndexOf(':');
if (colonIndex == -1 || colonIndex < bracketIndex) {
this.host = input;
this.port = DEFAULT_PORT;
}
else {
this.host = input.substring(0, colonIndex);
this.port = Integer.parseInt(input.substring(colonIndex + 1));
}
}
}
}

58
module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/PropertiesAmqpConnectionDetails.java

@ -0,0 +1,58 @@
/*
* 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.jspecify.annotations.Nullable;
/**
* Adapts {@link AmqpProperties} to {@link AmqpConnectionDetails}.
*
* @author Eddú Meléndez
*/
class PropertiesAmqpConnectionDetails implements AmqpConnectionDetails {
private final AmqpProperties properties;
PropertiesAmqpConnectionDetails(AmqpProperties properties) {
this.properties = properties;
}
@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 Address getAddress() {
String address = this.properties.determineAddress();
int portSeparatorIndex = address.lastIndexOf(':');
String host = address.substring(0, portSeparatorIndex);
String port = address.substring(portSeparatorIndex + 1);
return new Address(host, Integer.parseInt(port));
}
}

88
module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/PropertiesRabbitConnectionDetails.java

@ -1,88 +0,0 @@
/*
* 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 java.util.ArrayList;
import java.util.List;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.amqp.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<Address> getAddresses() {
List<Address> 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;
}
}

21
module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/RabbitAmqpAutoConfiguration.java

@ -31,14 +31,13 @@ import org.springframework.amqp.rabbitmq.client.config.RabbitAmqpListenerContain
import org.springframework.amqp.rabbitmq.client.listener.RabbitAmqpListenerContainer; import org.springframework.amqp.rabbitmq.client.listener.RabbitAmqpListenerContainer;
import org.springframework.amqp.support.converter.MessageConverter; import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.amqp.autoconfigure.RabbitConnectionDetails.Address; import org.springframework.boot.amqp.autoconfigure.AmqpConnectionDetails.Address;
import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.context.properties.PropertyMapper; import org.springframework.boot.context.properties.PropertyMapper;
import org.springframework.boot.ssl.SslBundles;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
@ -50,20 +49,20 @@ import org.springframework.context.annotation.Import;
*/ */
@AutoConfiguration @AutoConfiguration
@ConditionalOnClass({ RabbitAmqpTemplate.class, Connection.class }) @ConditionalOnClass({ RabbitAmqpTemplate.class, Connection.class })
@EnableConfigurationProperties(RabbitProperties.class) @EnableConfigurationProperties(AmqpProperties.class)
@Import(RabbitAnnotationDrivenConfiguration.class) @Import(RabbitAnnotationDrivenConfiguration.class)
public final class RabbitAmqpAutoConfiguration { public final class RabbitAmqpAutoConfiguration {
private final RabbitProperties properties; private final AmqpProperties properties;
RabbitAmqpAutoConfiguration(RabbitProperties properties) { RabbitAmqpAutoConfiguration(AmqpProperties properties) {
this.properties = properties; this.properties = properties;
} }
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
RabbitConnectionDetails rabbitConnectionDetails(ObjectProvider<SslBundles> sslBundles) { AmqpConnectionDetails rabbitConnectionDetails() {
return new PropertiesRabbitConnectionDetails(this.properties, sslBundles.getIfAvailable()); return new PropertiesAmqpConnectionDetails(this.properties);
} }
@Bean(name = "rabbitListenerContainerFactory") @Bean(name = "rabbitListenerContainerFactory")
@ -73,19 +72,19 @@ public final class RabbitAmqpAutoConfiguration {
RabbitAmqpListenerContainerFactory factory = new RabbitAmqpListenerContainerFactory(connectionFactory); RabbitAmqpListenerContainerFactory factory = new RabbitAmqpListenerContainerFactory(connectionFactory);
amqpContainerCustomizer.ifUnique(factory::setContainerCustomizer); amqpContainerCustomizer.ifUnique(factory::setContainerCustomizer);
RabbitProperties.AmqpContainer configuration = this.properties.getListener().getSimple(); AmqpProperties.AmqpContainer configuration = this.properties.getListener().getAmqp();
factory.setObservationEnabled(configuration.isObservationEnabled()); factory.setObservationEnabled(configuration.isObservationEnabled());
return factory; return factory;
} }
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
Environment rabbitAmqpEnvironment(RabbitConnectionDetails connectionDetails, Environment rabbitAmqpEnvironment(AmqpConnectionDetails connectionDetails,
ObjectProvider<AmqpEnvironmentBuilderCustomizer> customizers, ObjectProvider<AmqpEnvironmentBuilderCustomizer> customizers,
ObjectProvider<CredentialsProvider> credentialsProvider) { ObjectProvider<CredentialsProvider> credentialsProvider) {
PropertyMapper map = PropertyMapper.get(); PropertyMapper map = PropertyMapper.get();
EnvironmentConnectionSettings environmentConnectionSettings = new AmqpEnvironmentBuilder().connectionSettings(); EnvironmentConnectionSettings environmentConnectionSettings = new AmqpEnvironmentBuilder().connectionSettings();
Address address = connectionDetails.getFirstAddress(); Address address = connectionDetails.getAddress();
map.from(address::host).to(environmentConnectionSettings::host); map.from(address::host).to(environmentConnectionSettings::host);
map.from(address::port).to(environmentConnectionSettings::port); map.from(address::port).to(environmentConnectionSettings::port);
map.from(connectionDetails::getUsername).to(environmentConnectionSettings::username); map.from(connectionDetails::getUsername).to(environmentConnectionSettings::username);
@ -113,7 +112,7 @@ public final class RabbitAmqpAutoConfiguration {
if (messageConverter.getIfAvailable() != null) { if (messageConverter.getIfAvailable() != null) {
rabbitAmqpTemplate.setMessageConverter(messageConverter.getIfAvailable()); rabbitAmqpTemplate.setMessageConverter(messageConverter.getIfAvailable());
} }
RabbitProperties.Template templateProperties = this.properties.getTemplate(); AmqpProperties.Template templateProperties = this.properties.getTemplate();
PropertyMapper map = PropertyMapper.get(); PropertyMapper map = PropertyMapper.get();
map.from(templateProperties::getDefaultReceiveQueue).to(rabbitAmqpTemplate::setReceiveQueue); map.from(templateProperties::getDefaultReceiveQueue).to(rabbitAmqpTemplate::setReceiveQueue);

1364
module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/autoconfigure/RabbitProperties.java

File diff suppressed because it is too large Load Diff

33
module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/docker/compose/RabbitDockerComposeConnectionDetailsFactory.java

@ -16,23 +16,20 @@
package org.springframework.boot.amqp.docker.compose; package org.springframework.boot.amqp.docker.compose;
import java.util.List;
import org.jspecify.annotations.Nullable; import org.jspecify.annotations.Nullable;
import org.springframework.boot.amqp.autoconfigure.RabbitConnectionDetails; import org.springframework.boot.amqp.autoconfigure.AmqpConnectionDetails;
import org.springframework.boot.docker.compose.core.RunningService; 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.DockerComposeConnectionDetailsFactory;
import org.springframework.boot.docker.compose.service.connection.DockerComposeConnectionSource; import org.springframework.boot.docker.compose.service.connection.DockerComposeConnectionSource;
/** /**
* {@link DockerComposeConnectionDetailsFactory} to create {@link RabbitConnectionDetails} * {@link DockerComposeConnectionDetailsFactory} to create {@link AmqpConnectionDetails}
* for a {@code rabbitmq} service. * for a {@code rabbitmq} service.
* *
* @author Andy Wilkinson * @author Eddú Meléndez
*/ */
class RabbitDockerComposeConnectionDetailsFactory class RabbitDockerComposeConnectionDetailsFactory extends DockerComposeConnectionDetailsFactory<AmqpConnectionDetails> {
extends DockerComposeConnectionDetailsFactory<RabbitConnectionDetails> {
private static final int RABBITMQ_PORT = 5672; private static final int RABBITMQ_PORT = 5672;
@ -41,10 +38,9 @@ class RabbitDockerComposeConnectionDetailsFactory
} }
@Override @Override
protected @Nullable RabbitConnectionDetails getDockerComposeConnectionDetails( protected @Nullable AmqpConnectionDetails getDockerComposeConnectionDetails(DockerComposeConnectionSource source) {
DockerComposeConnectionSource source) {
try { try {
return new RabbitDockerComposeConnectionDetails(source.getRunningService()); return new AmqpDockerComposeConnectionDetails(source.getRunningService());
} }
catch (IllegalStateException ex) { catch (IllegalStateException ex) {
return null; return null;
@ -52,20 +48,19 @@ class RabbitDockerComposeConnectionDetailsFactory
} }
/** /**
* {@link RabbitConnectionDetails} backed by a {@code rabbitmq} * {@link AmqpConnectionDetails} backed by a {@code rabbitmq} {@link RunningService}.
* {@link RunningService}.
*/ */
static class RabbitDockerComposeConnectionDetails extends DockerComposeConnectionDetails static class AmqpDockerComposeConnectionDetails extends DockerComposeConnectionDetails
implements RabbitConnectionDetails { implements AmqpConnectionDetails {
private final RabbitEnvironment environment; private final RabbitEnvironment environment;
private final List<Address> addresses; private final Address address;
protected RabbitDockerComposeConnectionDetails(RunningService service) { protected AmqpDockerComposeConnectionDetails(RunningService service) {
super(service); super(service);
this.environment = new RabbitEnvironment(service.env()); this.environment = new RabbitEnvironment(service.env());
this.addresses = List.of(new Address(service.host(), service.ports().get(RABBITMQ_PORT))); this.address = new Address(service.host(), service.ports().get(RABBITMQ_PORT));
} }
@Override @Override
@ -84,8 +79,8 @@ class RabbitDockerComposeConnectionDetailsFactory
} }
@Override @Override
public List<Address> getAddresses() { public Address getAddress() {
return this.addresses; return this.address;
} }
} }

85
module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/testcontainers/DeprecatedRabbitContainerConnectionDetailsFactory.java

@ -1,85 +0,0 @@
/*
* 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.testcontainers;
import java.net.URI;
import java.util.List;
import org.jspecify.annotations.Nullable;
import org.testcontainers.containers.RabbitMQContainer;
import org.springframework.boot.amqp.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<RabbitMQContainer, RabbitConnectionDetails> {
@Override
protected RabbitConnectionDetails getContainerConnectionDetails(
ContainerConnectionSource<RabbitMQContainer> source) {
return new RabbitMqContainerConnectionDetails(source);
}
/**
* {@link RabbitConnectionDetails} backed by a {@link ContainerConnectionSource}.
*/
private static final class RabbitMqContainerConnectionDetails extends ContainerConnectionDetails<RabbitMQContainer>
implements RabbitConnectionDetails {
private RabbitMqContainerConnectionDetails(ContainerConnectionSource<RabbitMQContainer> source) {
super(source);
}
@Override
public String getUsername() {
return getContainer().getAdminUsername();
}
@Override
public String getPassword() {
return getContainer().getAdminPassword();
}
@Override
public List<Address> 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();
}
}
}

31
module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/testcontainers/RabbitContainerConnectionDetailsFactory.java

@ -17,42 +17,37 @@
package org.springframework.boot.amqp.testcontainers; package org.springframework.boot.amqp.testcontainers;
import java.net.URI; import java.net.URI;
import java.util.List;
import org.jspecify.annotations.Nullable; import org.jspecify.annotations.Nullable;
import org.testcontainers.rabbitmq.RabbitMQContainer; import org.testcontainers.rabbitmq.RabbitMQContainer;
import org.springframework.boot.amqp.autoconfigure.RabbitConnectionDetails; import org.springframework.boot.amqp.autoconfigure.AmqpConnectionDetails;
import org.springframework.boot.ssl.SslBundle; import org.springframework.boot.ssl.SslBundle;
import org.springframework.boot.testcontainers.service.connection.ContainerConnectionDetailsFactory; import org.springframework.boot.testcontainers.service.connection.ContainerConnectionDetailsFactory;
import org.springframework.boot.testcontainers.service.connection.ContainerConnectionSource; import org.springframework.boot.testcontainers.service.connection.ContainerConnectionSource;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection; import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
/** /**
* {@link ContainerConnectionDetailsFactory} to create {@link RabbitConnectionDetails} * {@link ContainerConnectionDetailsFactory} to create {@link AmqpConnectionDetails} from
* from a {@link ServiceConnection @ServiceConnection}-annotated * a {@link ServiceConnection @ServiceConnection}-annotated {@link RabbitMQContainer}.
* {@link RabbitMQContainer}.
* *
* @author Moritz Halbritter * @author Eddú Meléndez
* @author Andy Wilkinson
* @author Phillip Webb
*/ */
class RabbitContainerConnectionDetailsFactory class RabbitContainerConnectionDetailsFactory
extends ContainerConnectionDetailsFactory<RabbitMQContainer, RabbitConnectionDetails> { extends ContainerConnectionDetailsFactory<RabbitMQContainer, AmqpConnectionDetails> {
@Override @Override
protected RabbitConnectionDetails getContainerConnectionDetails( protected AmqpConnectionDetails getContainerConnectionDetails(ContainerConnectionSource<RabbitMQContainer> source) {
ContainerConnectionSource<RabbitMQContainer> source) { return new AmqpMqContainerConnectionDetails(source);
return new RabbitMqContainerConnectionDetails(source);
} }
/** /**
* {@link RabbitConnectionDetails} backed by a {@link ContainerConnectionSource}. * {@link AmqpConnectionDetails} backed by a {@link ContainerConnectionSource}.
*/ */
static final class RabbitMqContainerConnectionDetails extends ContainerConnectionDetails<RabbitMQContainer> static final class AmqpMqContainerConnectionDetails extends ContainerConnectionDetails<RabbitMQContainer>
implements RabbitConnectionDetails { implements AmqpConnectionDetails {
private RabbitMqContainerConnectionDetails(ContainerConnectionSource<RabbitMQContainer> source) { private AmqpMqContainerConnectionDetails(ContainerConnectionSource<RabbitMQContainer> source) {
super(source); super(source);
} }
@ -67,9 +62,9 @@ class RabbitContainerConnectionDetailsFactory
} }
@Override @Override
public List<Address> getAddresses() { public Address getAddress() {
URI uri = URI.create((getSslBundle() != null) ? getContainer().getAmqpsUrl() : getContainer().getAmqpUrl()); URI uri = URI.create((getSslBundle() != null) ? getContainer().getAmqpsUrl() : getContainer().getAmqpUrl());
return List.of(new Address(uri.getHost(), uri.getPort())); return new Address(uri.getHost(), uri.getPort());
} }
@Override @Override

Loading…
Cancel
Save