Search code examples
spring-bootspring-data-redisredisson

How to define preDestroy order of redissonClient and embedded-redis


I'm using Redission and embedded-redis in unit tests. According to the documentation i start the redis server in the test class like this:

private RedisServer redisServer;

  @PostConstruct
  public void postConstruct() {
    if (redisServer == null || !redisServer.isActive()) {
      redisServer = RedisServer.builder()
                               .port(6900)
                               .setting("maxmemory 128M") 
                               .build();
      redisServer.start();
    }
  }

  @PreDestroy
  public void preDestroy() {
    redisServer.stop();
  }

and the redission client looks like this:

@Configuration
@ConditionalOnClass(RedissonClient.class)
public class RedissonConfiguration {

      @Bean(destroyMethod = "shutdown")
      public RedissonClient redissonClient() {
        Config config = new Config();
        config.useSingleServer()
              .setAddress("redis://localhost:6900");
    
        return Redisson.create(config);
      }
}

now i got the the following error in the logs:

[InstanceCleaner] r.e.AbstractRedisInstance Stopping redis server... [InstanceCleaner] r.e.AbstractRedisInstance : Redis exited [isson-netty-7-5] o.r.c.h.ErrorsLoggingHandler : Exception occured. Channel: [id: 0xa9eeeee5, L:/127.0.0.1:49429 - R:localhost/127.0.0.1:6699] java.io.IOException: Eine vorhandene Verbindung wurde vom Remotehost geschlossen

The problem is that preDestroy is called before the destroyMethod (shutdown) of the bean. Is there an other way to stop the server at the end?

I can't use @DependsOn at RedissonConfiguration because it would depend on a TestConfiguration class.


Solution

  • I found a solution. This interface is part of the normal prod classes. Now i can annotate the RedissonClient bean with dependsOn("EmbeddedRedis"). Not quite sure if i'm happy with it but it works....

    interface EmbeddedRedis {
    
      @Component(value = "EmbeddedRedis")
      @Profile("!local")
      class EmptyRedis implements EmbeddedRedis {
    
      }
    
      @Component(value = "EmbeddedRedis")
      @Profile("local")
      class Redis implements EmbeddedRedis, DisposableBean {
    
        private final int port;
    
        private RedisServer redisServer;
    
        public Redis(@Value("${spring.redis.port}")final int port) {
          this.port = port;
        }
    
        @PostConstruct
        public void postConstruct() {
          if (redisServer == null || !redisServer.isActive()) {
            redisServer = RedisServer.builder()
                                     .port(port)
                                     .setting("maxmemory 128M") 
                                     .build();
            redisServer.start();
          }
        }
    
        @Override
        public void destroy() {
          redisServer.stop();
        }
    
      }
    }