We have a spring boot application using jedis for connecting to redis and we use jedis for unit tests. Recently, due to a vulnerability, we updated to spring boot 3.0.6 + java 17 and all unit tests using jedis fail, we use spring-boot-starter-data-redis with jedis for unit tests. Be aware that downgrading back to spring boot 2.x.x (spring-boot-starter-data-redis gets downgraded to 2.x.x too) all unit tests work as expected.
I have shortened the stack thrown at failure, because the redis config and redis method is written in a our own library that we re-use across multiple apps:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'getClusterRedisConnectionFactory' defined in class path resource [com/sap/etd/cloud/commons/config/redis/RedisConfig.class]: Could not initialize cluster slots cache.
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1770) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:598) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:520) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:225) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1310) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1271) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveBean(DefaultListableBeanFactory.java:484) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:339) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:332) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1150) ~[spring-context-6.0.8.jar:6.0.8]
at com.sap.etd.cloud.commons.config.redis.RedisConfig.getRedisTemplate(RedisConfig.java:71) ~[streaming-commons-3.8.11.jar:3.8.11]
at com.sap.etd.cloud.commons.config.redis.RedisConfig$$SpringCGLIB$$0.CGLIB$getRedisTemplate$1(<generated>) ~[streaming-commons-3.8.11.jar:3.8.11]
at com.sap.etd.cloud.commons.config.redis.RedisConfig$$SpringCGLIB$$2.invoke(<generated>) ~[streaming-commons-3.8.11.jar:3.8.11]
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:258) ~[spring-core-6.0.8.jar:6.0.8]
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331) ~[spring-context-6.0.8.jar:6.0.8]
at com.sap.etd.cloud.commons.config.redis.RedisConfig$$SpringCGLIB$$0.getRedisTemplate(<generated>) ~[streaming-commons-3.8.11.jar:3.8.11]
at jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104) ~[?:?]
at java.lang.reflect.Method.invoke(Method.java:577) ~[?:?]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:139) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:655) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:493) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1332) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1162) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:560) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:520) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1417) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1337) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:887) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:245) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1352) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1189) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:560) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:520) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1417) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1337) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:887) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:245) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1352) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1189) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:560) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:520) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1417) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1337) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:887) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791) ~[spring-beans-6.0.8.jar:6.0.8]
... 90 more
Caused by: redis.clients.jedis.exceptions.JedisClusterOperationException: Could not initialize cluster slots cache.
at redis.clients.jedis.providers.ClusterConnectionProvider.initializeSlotsCache(ClusterConnectionProvider.java:56) ~[jedis-5.0.0-alpha1.jar:?]
at redis.clients.jedis.providers.ClusterConnectionProvider.<init>(ClusterConnectionProvider.java:32) ~[jedis-5.0.0-alpha1.jar:?]
at redis.clients.jedis.UnifiedJedis.<init>(UnifiedJedis.java:130) ~[jedis-5.0.0-alpha1.jar:?]
at redis.clients.jedis.JedisCluster.<init>(JedisCluster.java:179) ~[jedis-5.0.0-alpha1.jar:?]
at redis.clients.jedis.JedisCluster.<init>(JedisCluster.java:172) ~[jedis-5.0.0-alpha1.jar:?]
at org.springframework.data.redis.connection.jedis.JedisConnectionFactory.createCluster(JedisConnectionFactory.java:413) ~[spring-data-redis-3.0.5.jar:3.0.5]
at org.springframework.data.redis.connection.jedis.JedisConnectionFactory.createCluster(JedisConnectionFactory.java:377) ~[spring-data-redis-3.0.5.jar:3.0.5]
at org.springframework.data.redis.connection.jedis.JedisConnectionFactory.afterPropertiesSet(JedisConnectionFactory.java:300) ~[spring-data-redis-3.0.5.jar:3.0.5]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1816) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1766) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:598) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:520) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:225) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1310) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1271) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveBean(DefaultListableBeanFactory.java:484) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:339) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:332) ~[spring-beans-6.0.8.jar:6.0.8]
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1150) ~[spring-context-6.0.8.jar:6.0.8]
at com.sap.etd.cloud.commons.config.redis.RedisConfig.getRedisTemplate(RedisConfig.java:71) ~[streaming-commons-3.8.11.jar:3.8.11]
at com.sap.etd.cloud.commons.config.redis.RedisConfig$$SpringCGLIB$$0.CGLIB$getRedisTemplate$1(<generated>) ~[streaming-commons-3.8.11.jar:3.8.11]
at com.sap.etd.cloud.commons.config.redis.RedisConfig$$SpringCGLIB$$2.invoke(<generated>) ~[streaming-commons-3.8.11.jar:3.8.11]
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:258) ~[spring-core-6.0.8.jar:6.0.8]
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331) ~[spring-context-6.0.8.jar:6.0.8]
at com.sap.etd.cloud.commons.config.redis.RedisConfig$$SpringCGLIB$$0.getRedisTemplate(<generated>) ~[streaming-commons-3.8.11.jar:3.8.11]
at jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104) ~[?:?]
This is our RedisConfig class file
@Configuration
@EnableAsync
@Log4j2
public class RedisConfig {
private final ApplicationContext context;
private final CfEnvUtils cfEnvUtils;
@Autowired
public RedisConfig(ApplicationContext context, CfEnvUtils cfEnvUtils) {
this.context = context;
this.cfEnvUtils = cfEnvUtils;
}
private JedisClientConfiguration getJedisClientConfiguration() {
log.info("Preparing Jedis Client Config for ");
return JedisClientConfiguration.builder().useSsl().build();
}
@Bean
public RedisConnectionFactory getClusterRedisConnectionFactory() {
if (cfEnvUtils.isInCloud()) {
CfEnv cfEnv = new CfEnv();
String redisHost = cfEnv.findCredentialsByTag(REDIS_TAG).getHost();
String redisPort = cfEnv.findCredentialsByTag(REDIS_TAG).getPort();
String redisPassword = cfEnv.findCredentialsByTag(REDIS_TAG).getPassword();
JedisConnectionFactory jcf;
JedisClientConfiguration clientConfig = getJedisClientConfiguration();
RedisClusterConfiguration clusterConfiguration = new RedisClusterConfiguration(
Collections.singletonList(redisHost + ":" + redisPort));
clusterConfiguration.setPassword(redisPassword);
jcf = new JedisConnectionFactory(clusterConfiguration, clientConfig);
return jcf;
} else {
JedisClientConfiguration clientConfig = getJedisClientConfiguration();
RedisClusterConfiguration clusterConfiguration = new RedisClusterConfiguration(
Collections.singletonList("localhost:" + 6379));
JedisConnectionFactory jcf;
jcf = new JedisConnectionFactory(clusterConfiguration, clientConfig);
return jcf;
}
}
@Bean
public StringRedisTemplate getRedisTemplate() {
StringRedisTemplate stringRedisTemplate = new StringRedisTemplate(context.getBean(RedisConnectionFactory.class));
stringRedisTemplate.setEnableTransactionSupport(true);
return stringRedisTemplate;
}
}
Notice that the main error is redis.clients.jedis.exceptions.JedisClusterOperationException: Could not initialize cluster slots cache.
which refers to the initialisation of the jedis on localhost:6379.
I am assuming that spring-boot 3.0.6 is not prepared for jedis 4.3.2 or I am missing something that has changed in the configurations.
I have tried different jedis versions and spring-boot to make it work but I am missing the root cause.
You can find the pom.xml
file here
You can find the output of mvn dependency:tree
here.
UPDATE Debugging JedisConnectionException resulted to: "Failed to connect to any host resolved for DNS name."
I wonder what is in your unit tests. Could it be just limited to creating a cluster connection object? Without executing any other command?
Why I'm wondering this because of a certain difference between Jedis 3.x and Jedis 4+ which seems to matter in your case.
In Jedis 3.x, when a JedisCluster object was being created with all cluster nodes down/unavailable, the constructor would not throw any exception and the object would be created BUT it would be a stale object with which no server operations can be made.
Jedis 4.0 onwards started throwing exception in this case with message Could not initialize cluster slots cache.
.