Skip to content

Commit 659667b

Browse files
committed
Merge pull request #26982 from bono007
* gh-26982: Polish "Add Rabbit connection factory configurers" Add Rabbit connection factory configurers Closes gh-26982
2 parents a5ec756 + 2c8658c commit 659667b

File tree

4 files changed

+257
-60
lines changed

4 files changed

+257
-60
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* Copyright 2012-2021 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.autoconfigure.amqp;
18+
19+
import org.springframework.amqp.rabbit.connection.AbstractConnectionFactory;
20+
import org.springframework.amqp.rabbit.connection.ConnectionNameStrategy;
21+
import org.springframework.boot.context.properties.PropertyMapper;
22+
import org.springframework.util.Assert;
23+
24+
/**
25+
* Configures {@link AbstractConnectionFactory Rabbit ConnectionFactory} with sensible
26+
* defaults.
27+
*
28+
* @param <T> the connection factory type.
29+
* @author Chris Bono
30+
* @since 2.6.0
31+
*/
32+
public abstract class AbstractConnectionFactoryConfigurer<T extends AbstractConnectionFactory> {
33+
34+
private final RabbitProperties rabbitProperties;
35+
36+
private ConnectionNameStrategy connectionNameStrategy;
37+
38+
protected AbstractConnectionFactoryConfigurer(RabbitProperties properties) {
39+
Assert.notNull(properties, "RabbitProperties must not be null");
40+
this.rabbitProperties = properties;
41+
}
42+
43+
protected final ConnectionNameStrategy getConnectionNameStrategy() {
44+
return this.connectionNameStrategy;
45+
}
46+
47+
protected final void setConnectionNameStrategy(ConnectionNameStrategy connectionNameStrategy) {
48+
this.connectionNameStrategy = connectionNameStrategy;
49+
}
50+
51+
/**
52+
* Configures the given {@code connectionFactory} with sensible defaults.
53+
* @param connectionFactory connection factory to configure
54+
*/
55+
public final void configure(T connectionFactory) {
56+
Assert.notNull(connectionFactory, "ConnectionFactory must not be null");
57+
PropertyMapper map = PropertyMapper.get();
58+
map.from(this.rabbitProperties::determineAddresses).to(connectionFactory::setAddresses);
59+
map.from(this.rabbitProperties::getAddressShuffleMode).whenNonNull()
60+
.to(connectionFactory::setAddressShuffleMode);
61+
map.from(this.connectionNameStrategy).whenNonNull().to(connectionFactory::setConnectionNameStrategy);
62+
configure(connectionFactory, this.rabbitProperties);
63+
}
64+
65+
/**
66+
* Configures the given {@code connectionFactory} using the given
67+
* {@code rabbitProperties}.
68+
* @param connectionFactory connection factory to configure
69+
* @param rabbitProperties properties to use for the configuration
70+
*/
71+
protected abstract void configure(T connectionFactory, RabbitProperties rabbitProperties);
72+
73+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Copyright 2012-2021 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.autoconfigure.amqp;
18+
19+
import java.time.Duration;
20+
21+
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
22+
import org.springframework.boot.context.properties.PropertyMapper;
23+
24+
/**
25+
* Configures Rabbit {@link CachingConnectionFactory} with sensible defaults.
26+
*
27+
* @author Chris Bono
28+
* @since 2.6.0
29+
*/
30+
public class CachingConnectionFactoryConfigurer extends AbstractConnectionFactoryConfigurer<CachingConnectionFactory> {
31+
32+
public CachingConnectionFactoryConfigurer(RabbitProperties properties) {
33+
super(properties);
34+
}
35+
36+
@Override
37+
public void configure(CachingConnectionFactory connectionFactory, RabbitProperties rabbitProperties) {
38+
PropertyMapper map = PropertyMapper.get();
39+
map.from(rabbitProperties::isPublisherReturns).to(connectionFactory::setPublisherReturns);
40+
map.from(rabbitProperties::getPublisherConfirmType).whenNonNull()
41+
.to(connectionFactory::setPublisherConfirmType);
42+
RabbitProperties.Cache.Channel channel = rabbitProperties.getCache().getChannel();
43+
map.from(channel::getSize).whenNonNull().to(connectionFactory::setChannelCacheSize);
44+
map.from(channel::getCheckoutTimeout).whenNonNull().as(Duration::toMillis)
45+
.to(connectionFactory::setChannelCheckoutTimeout);
46+
RabbitProperties.Cache.Connection connection = rabbitProperties.getCache().getConnection();
47+
map.from(connection::getMode).whenNonNull().to(connectionFactory::setCacheMode);
48+
map.from(connection::getSize).whenNonNull().to(connectionFactory::setConnectionCacheSize);
49+
}
50+
51+
}

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/amqp/RabbitAutoConfiguration.java

Lines changed: 32 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717
package org.springframework.boot.autoconfigure.amqp;
1818

19-
import java.time.Duration;
2019
import java.util.stream.Collectors;
2120

2221
import com.rabbitmq.client.Channel;
@@ -40,7 +39,6 @@
4039
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
4140
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
4241
import org.springframework.boot.context.properties.EnableConfigurationProperties;
43-
import org.springframework.boot.context.properties.PropertyMapper;
4442
import org.springframework.context.annotation.Bean;
4543
import org.springframework.context.annotation.Configuration;
4644
import org.springframework.context.annotation.Import;
@@ -84,6 +82,7 @@
8482
* @author Gary Russell
8583
* @author Phillip Webb
8684
* @author Artsiom Yudovin
85+
* @author Chris Bono
8786
* @since 1.0.0
8887
*/
8988
@Configuration(proxyBeanMethods = false)
@@ -93,73 +92,46 @@
9392
public class RabbitAutoConfiguration {
9493

9594
@Configuration(proxyBeanMethods = false)
96-
@ConditionalOnMissingBean(ConnectionFactory.class)
9795
protected static class RabbitConnectionFactoryCreator {
9896

9997
@Bean
100-
public CachingConnectionFactory rabbitConnectionFactory(RabbitProperties properties,
98+
@ConditionalOnMissingBean
99+
RabbitConnectionFactoryBeanConfigurer rabbitConnectionFactoryBeanConfigurer(RabbitProperties properties,
101100
ResourceLoader resourceLoader, ObjectProvider<CredentialsProvider> credentialsProvider,
102-
ObjectProvider<CredentialsRefreshService> credentialsRefreshService,
103-
ObjectProvider<ConnectionNameStrategy> connectionNameStrategy,
101+
ObjectProvider<CredentialsRefreshService> credentialsRefreshService) {
102+
RabbitConnectionFactoryBeanConfigurer configurer = new RabbitConnectionFactoryBeanConfigurer(resourceLoader,
103+
properties);
104+
configurer.setCredentialsProvider(credentialsProvider.getIfUnique());
105+
configurer.setCredentialsRefreshService(credentialsRefreshService.getIfUnique());
106+
return configurer;
107+
}
108+
109+
@Bean
110+
@ConditionalOnMissingBean
111+
CachingConnectionFactoryConfigurer rabbitConnectionFactoryConfigurer(RabbitProperties rabbitProperties,
112+
ObjectProvider<ConnectionNameStrategy> connectionNameStrategy) {
113+
CachingConnectionFactoryConfigurer configurer = new CachingConnectionFactoryConfigurer(rabbitProperties);
114+
configurer.setConnectionNameStrategy(connectionNameStrategy.getIfUnique());
115+
return configurer;
116+
}
117+
118+
@Bean
119+
@ConditionalOnMissingBean(ConnectionFactory.class)
120+
CachingConnectionFactory rabbitConnectionFactory(
121+
RabbitConnectionFactoryBeanConfigurer rabbitConnectionFactoryBeanConfigurer,
122+
CachingConnectionFactoryConfigurer rabbitCachingConnectionFactoryConfigurer,
104123
ObjectProvider<ConnectionFactoryCustomizer> connectionFactoryCustomizers) throws Exception {
105-
com.rabbitmq.client.ConnectionFactory connectionFactory = getRabbitConnectionFactoryBean(properties,
106-
resourceLoader, credentialsProvider, credentialsRefreshService).getObject();
124+
125+
RabbitConnectionFactoryBean connectionFactoryBean = new RabbitConnectionFactoryBean();
126+
rabbitConnectionFactoryBeanConfigurer.configure(connectionFactoryBean);
127+
connectionFactoryBean.afterPropertiesSet();
128+
com.rabbitmq.client.ConnectionFactory connectionFactory = connectionFactoryBean.getObject();
107129
connectionFactoryCustomizers.orderedStream()
108130
.forEach((customizer) -> customizer.customize(connectionFactory));
131+
109132
CachingConnectionFactory factory = new CachingConnectionFactory(connectionFactory);
110-
PropertyMapper map = PropertyMapper.get();
111-
map.from(properties::determineAddresses).to(factory::setAddresses);
112-
map.from(properties::getAddressShuffleMode).whenNonNull().to(factory::setAddressShuffleMode);
113-
map.from(properties::isPublisherReturns).to(factory::setPublisherReturns);
114-
map.from(properties::getPublisherConfirmType).whenNonNull().to(factory::setPublisherConfirmType);
115-
RabbitProperties.Cache.Channel channel = properties.getCache().getChannel();
116-
map.from(channel::getSize).whenNonNull().to(factory::setChannelCacheSize);
117-
map.from(channel::getCheckoutTimeout).whenNonNull().as(Duration::toMillis)
118-
.to(factory::setChannelCheckoutTimeout);
119-
RabbitProperties.Cache.Connection connection = properties.getCache().getConnection();
120-
map.from(connection::getMode).whenNonNull().to(factory::setCacheMode);
121-
map.from(connection::getSize).whenNonNull().to(factory::setConnectionCacheSize);
122-
map.from(connectionNameStrategy::getIfUnique).whenNonNull().to(factory::setConnectionNameStrategy);
123-
return factory;
124-
}
133+
rabbitCachingConnectionFactoryConfigurer.configure(factory);
125134

126-
private RabbitConnectionFactoryBean getRabbitConnectionFactoryBean(RabbitProperties properties,
127-
ResourceLoader resourceLoader, ObjectProvider<CredentialsProvider> credentialsProvider,
128-
ObjectProvider<CredentialsRefreshService> credentialsRefreshService) {
129-
RabbitConnectionFactoryBean factory = new RabbitConnectionFactoryBean();
130-
factory.setResourceLoader(resourceLoader);
131-
PropertyMapper map = PropertyMapper.get();
132-
map.from(properties::determineHost).whenNonNull().to(factory::setHost);
133-
map.from(properties::determinePort).to(factory::setPort);
134-
map.from(properties::determineUsername).whenNonNull().to(factory::setUsername);
135-
map.from(properties::determinePassword).whenNonNull().to(factory::setPassword);
136-
map.from(properties::determineVirtualHost).whenNonNull().to(factory::setVirtualHost);
137-
map.from(properties::getRequestedHeartbeat).whenNonNull().asInt(Duration::getSeconds)
138-
.to(factory::setRequestedHeartbeat);
139-
map.from(properties::getRequestedChannelMax).to(factory::setRequestedChannelMax);
140-
RabbitProperties.Ssl ssl = properties.getSsl();
141-
if (ssl.determineEnabled()) {
142-
factory.setUseSSL(true);
143-
map.from(ssl::getAlgorithm).whenNonNull().to(factory::setSslAlgorithm);
144-
map.from(ssl::getKeyStoreType).to(factory::setKeyStoreType);
145-
map.from(ssl::getKeyStore).to(factory::setKeyStore);
146-
map.from(ssl::getKeyStorePassword).to(factory::setKeyStorePassphrase);
147-
map.from(ssl::getKeyStoreAlgorithm).whenNonNull().to(factory::setKeyStoreAlgorithm);
148-
map.from(ssl::getTrustStoreType).to(factory::setTrustStoreType);
149-
map.from(ssl::getTrustStore).to(factory::setTrustStore);
150-
map.from(ssl::getTrustStorePassword).to(factory::setTrustStorePassphrase);
151-
map.from(ssl::getTrustStoreAlgorithm).whenNonNull().to(factory::setTrustStoreAlgorithm);
152-
map.from(ssl::isValidateServerCertificate)
153-
.to((validate) -> factory.setSkipServerCertificateValidation(!validate));
154-
map.from(ssl::getVerifyHostname).to(factory::setEnableHostnameVerification);
155-
}
156-
map.from(properties::getConnectionTimeout).whenNonNull().asInt(Duration::toMillis)
157-
.to(factory::setConnectionTimeout);
158-
map.from(properties::getChannelRpcTimeout).whenNonNull().asInt(Duration::toMillis)
159-
.to(factory::setChannelRpcTimeout);
160-
map.from(credentialsProvider::getIfUnique).whenNonNull().to(factory::setCredentialsProvider);
161-
map.from(credentialsRefreshService::getIfUnique).whenNonNull().to(factory::setCredentialsRefreshService);
162-
factory.afterPropertiesSet();
163135
return factory;
164136
}
165137

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*
2+
* Copyright 2012-2020 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.autoconfigure.amqp;
18+
19+
import java.time.Duration;
20+
21+
import com.rabbitmq.client.impl.CredentialsProvider;
22+
import com.rabbitmq.client.impl.CredentialsRefreshService;
23+
24+
import org.springframework.amqp.rabbit.connection.RabbitConnectionFactoryBean;
25+
import org.springframework.boot.context.properties.PropertyMapper;
26+
import org.springframework.core.io.ResourceLoader;
27+
import org.springframework.util.Assert;
28+
29+
/**
30+
* Configures {@link RabbitConnectionFactoryBean} with sensible defaults.
31+
*
32+
* @author Chris Bono
33+
* @since 2.6.0
34+
*/
35+
public class RabbitConnectionFactoryBeanConfigurer {
36+
37+
private final RabbitProperties rabbitProperties;
38+
39+
private final ResourceLoader resourceLoader;
40+
41+
private CredentialsProvider credentialsProvider;
42+
43+
private CredentialsRefreshService credentialsRefreshService;
44+
45+
public RabbitConnectionFactoryBeanConfigurer(ResourceLoader resourceLoader, RabbitProperties properties) {
46+
this.resourceLoader = resourceLoader;
47+
this.rabbitProperties = properties;
48+
}
49+
50+
public void setCredentialsProvider(CredentialsProvider credentialsProvider) {
51+
this.credentialsProvider = credentialsProvider;
52+
}
53+
54+
public void setCredentialsRefreshService(CredentialsRefreshService credentialsRefreshService) {
55+
this.credentialsRefreshService = credentialsRefreshService;
56+
}
57+
58+
/**
59+
* Configure the specified rabbit connection factory bean. The factory bean can be
60+
* further tuned and default settings can be overridden. It is the repsonsiblity of
61+
* the caller to invoke {@link RabbitConnectionFactoryBean#afterPropertiesSet()}
62+
* though.
63+
* @param factory the {@link RabbitConnectionFactoryBean} instance to configure
64+
*/
65+
public void configure(RabbitConnectionFactoryBean factory) {
66+
Assert.notNull(factory, "RabbitConnectionFactoryBean must not be null");
67+
factory.setResourceLoader(this.resourceLoader);
68+
PropertyMapper map = PropertyMapper.get();
69+
map.from(this.rabbitProperties::determineHost).whenNonNull().to(factory::setHost);
70+
map.from(this.rabbitProperties::determinePort).to(factory::setPort);
71+
map.from(this.rabbitProperties::determineUsername).whenNonNull().to(factory::setUsername);
72+
map.from(this.rabbitProperties::determinePassword).whenNonNull().to(factory::setPassword);
73+
map.from(this.rabbitProperties::determineVirtualHost).whenNonNull().to(factory::setVirtualHost);
74+
map.from(this.rabbitProperties::getRequestedHeartbeat).whenNonNull().asInt(Duration::getSeconds)
75+
.to(factory::setRequestedHeartbeat);
76+
map.from(this.rabbitProperties::getRequestedChannelMax).to(factory::setRequestedChannelMax);
77+
RabbitProperties.Ssl ssl = this.rabbitProperties.getSsl();
78+
if (ssl.determineEnabled()) {
79+
factory.setUseSSL(true);
80+
map.from(ssl::getAlgorithm).whenNonNull().to(factory::setSslAlgorithm);
81+
map.from(ssl::getKeyStoreType).to(factory::setKeyStoreType);
82+
map.from(ssl::getKeyStore).to(factory::setKeyStore);
83+
map.from(ssl::getKeyStorePassword).to(factory::setKeyStorePassphrase);
84+
map.from(ssl::getKeyStoreAlgorithm).whenNonNull().to(factory::setKeyStoreAlgorithm);
85+
map.from(ssl::getTrustStoreType).to(factory::setTrustStoreType);
86+
map.from(ssl::getTrustStore).to(factory::setTrustStore);
87+
map.from(ssl::getTrustStorePassword).to(factory::setTrustStorePassphrase);
88+
map.from(ssl::getTrustStoreAlgorithm).whenNonNull().to(factory::setTrustStoreAlgorithm);
89+
map.from(ssl::isValidateServerCertificate)
90+
.to((validate) -> factory.setSkipServerCertificateValidation(!validate));
91+
map.from(ssl::getVerifyHostname).to(factory::setEnableHostnameVerification);
92+
}
93+
map.from(this.rabbitProperties::getConnectionTimeout).whenNonNull().asInt(Duration::toMillis)
94+
.to(factory::setConnectionTimeout);
95+
map.from(this.rabbitProperties::getChannelRpcTimeout).whenNonNull().asInt(Duration::toMillis)
96+
.to(factory::setChannelRpcTimeout);
97+
map.from(this.credentialsProvider).whenNonNull().to(factory::setCredentialsProvider);
98+
map.from(this.credentialsRefreshService).whenNonNull().to(factory::setCredentialsRefreshService);
99+
}
100+
101+
}

0 commit comments

Comments
 (0)