Home > Software engineering >  Spring boot application fails on startup when Redis server is down
Spring boot application fails on startup when Redis server is down

Time:09-02

This is a snippet of my configuration class

@Configuration
@EnableCaching
public class RedisCacheConfig extends CachingConfigurerSupport {

@Bean
public LettuceConnectionFactory redisConnectionFactory() {
    return new LettuceConnectionFactory(new RedisStandaloneConfiguration(),
            LettuceClientConfiguration.builder()
                    .commandTimeout(Duration.ofMillis(1000))
                    .build());
}

@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
    RedisTemplate<Object, Object> template = new RedisTemplate<>();
    template.setConnectionFactory(connectionFactory);
    return template;
}

//Cache manager configurations follow here...

When the local redis server is up the app works flawlessly but when the redis is down the startup fails with the following:

org.springframework.data.redis.RedisConnectionFailureException: Unable to connect to Redis; nested exception is io.lettuce.core.RedisConnectionException: Unable to connect to localhost:6379 at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$ExceptionTranslatingConnectionProvider.translateException(LettuceConnectionFactory.java:1689) at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$ExceptionTranslatingConnectionProvider.getConnection(LettuceConnectionFactory.java:1597) at
...
...
...
...
14 common frames omitted Caused by: io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused: no further information: localhost/127.0.0.1:6379 Caused by: java.net.ConnectException: Connection refused: no further information at java.base/sun.nio.ch.SocketChannelImpl.checkConnect(Native Method) at java.base/sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:777)

When the cache server is down I would like the app to go on and just run as if there was no caching used all. Any try/catch solutions that I found in other questions did not do the trick. Any ideas?

CodePudding user response:

I think it's possible even if I didn't try it. You can use a conditional check on the beans related to Redis. Using something like this

public class OnRedisAvailableCondition implements Condition {

  @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        RedisClient redisClient = RedisClient.create("redis://password@localhost:6379/");
        StatefulRedisConnection<String, String> connection
             = redisClient.connect();
        return connection.isOpen();
    }
}

and then on your bean loading you can put the condition

@Bean
@Conditional(OnRedisAvailableCondition.class)

But it can works if your using Redis as a cache manager, so only with the Spring annotations and not with direct Redis commands. In that case you can substitute it with an in-memory implementation (something like ConcurrentMapCacheManager).

  • Related