Commit d17c4755 authored by Stephane Nicoll's avatar Stephane Nicoll

Polish "Enable Redis connection pool if commons-pool2 is available"

See gh-26326
parent 55ff1630
...@@ -41,7 +41,6 @@ import org.springframework.util.StringUtils; ...@@ -41,7 +41,6 @@ import org.springframework.util.StringUtils;
* *
* @author Mark Paluch * @author Mark Paluch
* @author Stephane Nicoll * @author Stephane Nicoll
* @author Weix Sun
*/ */
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ GenericObjectPool.class, JedisConnection.class, Jedis.class }) @ConditionalOnClass({ GenericObjectPool.class, JedisConnection.class, Jedis.class })
...@@ -77,7 +76,7 @@ class JedisConnectionConfiguration extends RedisConnectionConfiguration { ...@@ -77,7 +76,7 @@ class JedisConnectionConfiguration extends RedisConnectionConfiguration {
ObjectProvider<JedisClientConfigurationBuilderCustomizer> builderCustomizers) { ObjectProvider<JedisClientConfigurationBuilderCustomizer> builderCustomizers) {
JedisClientConfigurationBuilder builder = applyProperties(JedisClientConfiguration.builder()); JedisClientConfigurationBuilder builder = applyProperties(JedisClientConfiguration.builder());
RedisProperties.Pool pool = getProperties().getJedis().getPool(); RedisProperties.Pool pool = getProperties().getJedis().getPool();
if (pool.isEnabled()) { if (isPoolEnabled(pool)) {
applyPooling(pool, builder); applyPooling(pool, builder);
} }
if (StringUtils.hasText(getProperties().getUrl())) { if (StringUtils.hasText(getProperties().getUrl())) {
......
...@@ -51,7 +51,6 @@ import org.springframework.util.StringUtils; ...@@ -51,7 +51,6 @@ import org.springframework.util.StringUtils;
* *
* @author Mark Paluch * @author Mark Paluch
* @author Andy Wilkinson * @author Andy Wilkinson
* @author Weix Sun
*/ */
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@ConditionalOnClass(RedisClient.class) @ConditionalOnClass(RedisClient.class)
...@@ -105,7 +104,7 @@ class LettuceConnectionConfiguration extends RedisConnectionConfiguration { ...@@ -105,7 +104,7 @@ class LettuceConnectionConfiguration extends RedisConnectionConfiguration {
} }
private LettuceClientConfigurationBuilder createBuilder(Pool pool) { private LettuceClientConfigurationBuilder createBuilder(Pool pool) {
if (pool.isEnabled()) { if (isPoolEnabled(pool)) {
return new PoolBuilderFactory().createBuilder(pool); return new PoolBuilderFactory().createBuilder(pool);
} }
return LettuceClientConfiguration.builder(); return LettuceClientConfiguration.builder();
......
/* /*
* Copyright 2012-2020 the original author or authors. * Copyright 2012-2021 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -22,12 +22,14 @@ import java.util.ArrayList; ...@@ -22,12 +22,14 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties.Pool;
import org.springframework.data.redis.connection.RedisClusterConfiguration; import org.springframework.data.redis.connection.RedisClusterConfiguration;
import org.springframework.data.redis.connection.RedisNode; import org.springframework.data.redis.connection.RedisNode;
import org.springframework.data.redis.connection.RedisPassword; import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisSentinelConfiguration; import org.springframework.data.redis.connection.RedisSentinelConfiguration;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration; import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
/** /**
...@@ -40,6 +42,9 @@ import org.springframework.util.StringUtils; ...@@ -40,6 +42,9 @@ import org.springframework.util.StringUtils;
*/ */
abstract class RedisConnectionConfiguration { abstract class RedisConnectionConfiguration {
private static final boolean COMMONS_POOL2_AVAILABLE = ClassUtils.isPresent("org.apache.commons.pool2.ObjectPool",
RedisConnectionConfiguration.class.getClassLoader());
private final RedisProperties properties; private final RedisProperties properties;
private final RedisSentinelConfiguration sentinelConfiguration; private final RedisSentinelConfiguration sentinelConfiguration;
...@@ -122,6 +127,11 @@ abstract class RedisConnectionConfiguration { ...@@ -122,6 +127,11 @@ abstract class RedisConnectionConfiguration {
return this.properties; return this.properties;
} }
protected boolean isPoolEnabled(Pool pool) {
Boolean enabled = pool.getEnabled();
return (enabled != null) ? enabled : COMMONS_POOL2_AVAILABLE;
}
private List<RedisNode> createSentinels(RedisProperties.Sentinel sentinel) { private List<RedisNode> createSentinels(RedisProperties.Sentinel sentinel) {
List<RedisNode> nodes = new ArrayList<>(); List<RedisNode> nodes = new ArrayList<>();
for (String node : sentinel.getNodes()) { for (String node : sentinel.getNodes()) {
......
...@@ -233,7 +233,11 @@ public class RedisProperties { ...@@ -233,7 +233,11 @@ public class RedisProperties {
*/ */
public static class Pool { public static class Pool {
private boolean enabled; /**
* Whether to enable the pool. Enabled automatically if "commons-pool2" is
* available.
*/
private Boolean enabled;
/** /**
* Maximum number of "idle" connections in the pool. Use a negative value to * Maximum number of "idle" connections in the pool. Use a negative value to
...@@ -267,11 +271,11 @@ public class RedisProperties { ...@@ -267,11 +271,11 @@ public class RedisProperties {
*/ */
private Duration timeBetweenEvictionRuns; private Duration timeBetweenEvictionRuns;
public boolean isEnabled() { public Boolean getEnabled() {
return this.enabled; return this.enabled;
} }
public void setEnabled(boolean enabled) { public void setEnabled(Boolean enabled) {
this.enabled = enabled; this.enabled = enabled;
} }
...@@ -406,13 +410,7 @@ public class RedisProperties { ...@@ -406,13 +410,7 @@ public class RedisProperties {
/** /**
* Jedis pool configuration. * Jedis pool configuration.
*/ */
private final Pool pool; private final Pool pool = new Pool();
public Jedis() {
Pool pool = new Pool();
pool.setEnabled(true);
this.pool = pool;
}
public Pool getPool() { public Pool getPool() {
return this.pool; return this.pool;
......
/*
* Copyright 2012-2021 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.autoconfigure.data.redis;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.boot.testsupport.classpath.ClassPathExclusions;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
import org.springframework.test.util.ReflectionTestUtils;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link RedisAutoConfiguration} when commons-pool2 is not on the classpath.
*
* @author Stephane Nicoll
*/
@ClassPathExclusions("commons-pool2-*.jar")
public class RedisAutoConfigurationLettuceWithoutCommonsPool2Tests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class));
@Test
void poolWithoutCommonsPool2IsDisabledByDefault() {
this.contextRunner.withPropertyValues("spring.redis.host:foo").run((context) -> {
LettuceConnectionFactory cf = context.getBean(LettuceConnectionFactory.class);
assertThat(cf.getHostName()).isEqualTo("foo");
assertThat(ReflectionTestUtils.getField(cf, "clientConfiguration"))
.isNotInstanceOf(LettucePoolingClientConfiguration.class);
});
}
}
...@@ -31,6 +31,7 @@ import org.apache.commons.pool2.impl.GenericObjectPoolConfig; ...@@ -31,6 +31,7 @@ import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties.Pool;
import org.springframework.boot.test.context.assertj.AssertableApplicationContext; import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.boot.test.context.runner.ContextConsumer; import org.springframework.boot.test.context.runner.ContextConsumer;
...@@ -156,25 +157,24 @@ class RedisAutoConfigurationTests { ...@@ -156,25 +157,24 @@ class RedisAutoConfigurationTests {
} }
@Test @Test
void testRedisConfigurationWithPoolUsingDefaultValue() { void testRedisConfigurationUsePoolByDefault() {
this.contextRunner.withPropertyValues("spring.redis.host:foo", "spring.redis.lettuce.pool.enabled:true") Pool defaultPool = new RedisProperties().getLettuce().getPool();
.run((context) -> { this.contextRunner.withPropertyValues("spring.redis.host:foo").run((context) -> {
LettuceConnectionFactory cf = context.getBean(LettuceConnectionFactory.class); LettuceConnectionFactory cf = context.getBean(LettuceConnectionFactory.class);
assertThat(cf.getHostName()).isEqualTo("foo"); assertThat(cf.getHostName()).isEqualTo("foo");
GenericObjectPoolConfig<?> poolConfig = getPoolingClientConfiguration(cf).getPoolConfig(); GenericObjectPoolConfig<?> poolConfig = getPoolingClientConfiguration(cf).getPoolConfig();
assertThat(poolConfig.getMinIdle()).isEqualTo(0); assertThat(poolConfig.getMinIdle()).isEqualTo(defaultPool.getMinIdle());
assertThat(poolConfig.getMaxIdle()).isEqualTo(8); assertThat(poolConfig.getMaxIdle()).isEqualTo(defaultPool.getMaxIdle());
assertThat(poolConfig.getMaxTotal()).isEqualTo(8); assertThat(poolConfig.getMaxTotal()).isEqualTo(defaultPool.getMaxActive());
assertThat(poolConfig.getMaxWaitMillis()).isEqualTo(-1); assertThat(poolConfig.getMaxWaitMillis()).isEqualTo(defaultPool.getMaxWait().toMillis());
}); });
} }
@Test @Test
void testRedisConfigurationWithPoolUsingCustomValue() { void testRedisConfigurationWithCustomPoolSettings() {
this.contextRunner.withPropertyValues("spring.redis.host:foo", "spring.redis.lettuce.pool.enabled:true", this.contextRunner.withPropertyValues("spring.redis.host:foo", "spring.redis.lettuce.pool.min-idle:1",
"spring.redis.lettuce.pool.min-idle:1", "spring.redis.lettuce.pool.max-idle:4", "spring.redis.lettuce.pool.max-idle:4", "spring.redis.lettuce.pool.max-active:16",
"spring.redis.lettuce.pool.max-active:16", "spring.redis.lettuce.pool.max-wait:2000", "spring.redis.lettuce.pool.max-wait:2000", "spring.redis.lettuce.pool.time-between-eviction-runs:30000",
"spring.redis.lettuce.pool.time-between-eviction-runs:30000",
"spring.redis.lettuce.shutdown-timeout:1000").run((context) -> { "spring.redis.lettuce.shutdown-timeout:1000").run((context) -> {
LettuceConnectionFactory cf = context.getBean(LettuceConnectionFactory.class); LettuceConnectionFactory cf = context.getBean(LettuceConnectionFactory.class);
assertThat(cf.getHostName()).isEqualTo("foo"); assertThat(cf.getHostName()).isEqualTo("foo");
......
...@@ -46,7 +46,7 @@ If you use Jedis, `JedisClientConfigurationBuilderCustomizer` is also available. ...@@ -46,7 +46,7 @@ If you use Jedis, `JedisClientConfigurationBuilderCustomizer` is also available.
If you add your own `@Bean` of any of the auto-configured types, it replaces the default (except in the case of `RedisTemplate`, when the exclusion is based on the bean name, `redisTemplate`, not its type). If you add your own `@Bean` of any of the auto-configured types, it replaces the default (except in the case of `RedisTemplate`, when the exclusion is based on the bean name, `redisTemplate`, not its type).
A pooled connection factory is auto-configured if `commons-pool2` is on the classpath and at least one `Pool` option of {spring-boot-autoconfigure-module-code}/data/redis/RedisProperties.java[`RedisProperties`] is set. By default, a pooled connection factory is auto-configured if `commons-pool2` is on the classpath.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment