Skip to content
Advertisement

Getting a key/keys from ReactiveRedisOperations always return empty result

I am migrating my traditional Redis cache to the Spring Data Reactive Redis. After migration I would like to test if my new integration works as expected but I faced a problem with getting key/keys from particular Redis Db, namely: My redisConfiguration class looks like this:

import java.time.Duration;
import java.util.Properties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.PropertySource;
import org.springframework.data.redis.connection.ReactiveRedisConnectionFactory;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.ReactiveRedisOperations;
import org.springframework.data.redis.core.ReactiveRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializationContext.RedisSerializationContextBuilder;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
@PropertySource("classpath:redis.properties")
@Slf4j
public class RedisConfiguration {

  private static final String REDIS_PROPERTIES = "redis.properties";
  private final Properties redisProperties = readConfigurationFile(REDIS_PROPERTIES);

  @Value("${redis.host}")
  private String host;

  @Value("${redis.port}")
  private int port;

  @Value("${redis.password}")
  private String password;

  @Value("${redis.timeout}")
  private String timeout;

  @Bean(name = "reactiveRedisConnectionFactory")
  @Primary
  public ReactiveRedisConnectionFactory reactiveRedisConnectionFactory() {
    return new LettuceConnectionFactory();
  }

  @Bean(name ="reactiveRedisTemplate")
  public ReactiveRedisOperations<String, Object> reactiveRedisTemplate(
      @Qualifier(value = "reactiveRedisConnectionFactory") ReactiveRedisConnectionFactory factory) {
    return prepareRedisTemplate(factory);
  }

  @Bean(name = "reactiveRedisUserConnectionFactory")
  public ReactiveRedisConnectionFactory reactiveRedisUserConnectionFactory() {
    RedisStandaloneConfiguration redisConfiguration = new RedisStandaloneConfiguration();
    String userDb = getProperty(redisProperties, RedisDb.USER_DB);

    setRedisProperties(redisConfiguration, userDb);

    LettuceClientConfiguration clientConfiguration =
        LettuceClientConfiguration.builder()
            .commandTimeout(Duration.ofMillis(Long.parseLong(timeout)))
            .build();

    logRedisConnectionDetails(redisConfiguration, clientConfiguration);

    return new LettuceConnectionFactory(redisConfiguration, clientConfiguration);
  }

  @Bean(name = "reactiveUserRedisTemplate")
  public ReactiveRedisOperations<String, Object> userRedisTemplate(
      @Qualifier(value = "reactiveRedisUserConnectionFactory")
          ReactiveRedisConnectionFactory connectionFactory) {
    return prepareRedisTemplate(connectionFactory);
  }

  @Bean(name = "redisRegistrationTokenConnectionFactory")
  public ReactiveRedisConnectionFactory reactiveRedisRegistrationTokenConnectionFactory() {
    RedisStandaloneConfiguration redisConfiguration = new RedisStandaloneConfiguration();

    String registrationTokenDb = getProperty(redisProperties, RedisDb.REGISTRATION_TOKEN_DB);
    setRedisProperties(redisConfiguration, registrationTokenDb);

    LettuceClientConfiguration clientConfiguration =
        LettuceClientConfiguration.builder()
            .commandTimeout(Duration.ofMillis(Long.parseLong(timeout)))
            .build();

    logRedisConnectionDetails(redisConfiguration, clientConfiguration);

    return new LettuceConnectionFactory(redisConfiguration, clientConfiguration);
  }

  @Bean(name = "reactiveRegistrationTokenRedisTemplate")
  public ReactiveRedisOperations<String, Object> registrationTokenRedisTemplate(
      @Qualifier(value = "redisRegistrationTokenConnectionFactory")
          ReactiveRedisConnectionFactory connectionFactory) {
    return prepareRedisTemplate(connectionFactory);
  }

  @Bean(name = "reactiveRedisWhitelistingConnectionFactory")
  public ReactiveRedisConnectionFactory redisWhitelistingConnectionFactory() {
    RedisStandaloneConfiguration redisConfiguration = new RedisStandaloneConfiguration();

    String whitelistingDb = getProperty(redisProperties, RedisDb.WHITELISTING_DB);
    setRedisProperties(redisConfiguration, whitelistingDb);

    LettuceClientConfiguration clientConfiguration =
        LettuceClientConfiguration.builder()
            .commandTimeout(Duration.ofMillis(Long.parseLong(timeout)))
            .build();

    logRedisConnectionDetails(redisConfiguration, clientConfiguration);

    return new LettuceConnectionFactory(redisConfiguration, clientConfiguration);
  }

  @Bean(name = "reactiveWhitelistingRedisTemplate")
  public ReactiveRedisOperations<String, Object> reactiveWhitelistingRedisTemplate(
      @Qualifier(value = "reactiveRedisWhitelistingConnectionFactory")
          ReactiveRedisConnectionFactory connectionFactory) {
    return prepareRedisTemplate(connectionFactory);
  }

  @Bean(name = "redisSerializer")
  public Jackson2JsonRedisSerializer<Object> redisSerializer() {
    return new Jackson2JsonRedisSerializer<>(Object.class);
  }

  private ReactiveRedisOperations<String, Object> prepareRedisTemplate(ReactiveRedisConnectionFactory connectionFactory) {
    Jackson2JsonRedisSerializer<Object> redisSerializer =
        new Jackson2JsonRedisSerializer<>(Object.class);

    RedisSerializationContextBuilder<String, Object> serializationContext =
        RedisSerializationContext.newSerializationContext(new StringRedisSerializer());

    RedisSerializationContext<String, Object> context =
        serializationContext
            .value(redisSerializer)
            .hashKey(redisSerializer)
            .hashValue(redisSerializer)
            .build();
    return new ReactiveRedisTemplate<>(connectionFactory, context);
  }

  private void setRedisProperties(RedisStandaloneConfiguration redisConfiguration, String redisDb) {
    redisConfiguration.setHostName(host);
    redisConfiguration.setPort(port);
    redisConfiguration.setDatabase(Integer.parseInt(redisDb));
    redisConfiguration.setPassword(RedisPassword.of(password));
  }

  private void logRedisConnectionDetails(
      RedisStandaloneConfiguration redisConfiguration,
      LettuceClientConfiguration clientConfiguration) {
    log.info(
        "Connected to Redis host: {}, port: {}, database: {}, commandTimeout: {}",
        redisConfiguration.getHostName(),
        redisConfiguration.getPort(),
        redisConfiguration.getDatabase(),
        clientConfiguration.getCommandTimeout().toSeconds());
  }
}

My “test” class looks like:

@SpringBootApplication
@Slf4j
public class ApiGatewayApplication implements CommandLineRunner {

  private final ReactiveRedisOperations<String, Object> reactiveWhitelistingRedisTemplate;
  private final ReactiveRedisOperations<String, Object> reactiveUserRedisTemplate;

  public ApiGatewayApplication(
      @Qualifier(value = "reactiveWhitelistingRedisTemplate") ReactiveRedisOperations<String, Object> reactiveWhitelistingRedisTemplate,
      @Qualifier(value = "reactiveUserRedisTemplate") ReactiveRedisOperations<String, Object> reactiveUserRedisTemplate) {
    this.reactiveWhitelistingRedisTemplate = reactiveWhitelistingRedisTemplate;
    this.reactiveUserRedisTemplate = reactiveUserRedisTemplate;
  }

  public static void main(String[] args) {
    SpringApplication.run(ApiGatewayApplication.class, args);
  }

  @Override
  public void run(String... args) {

    log.info("CASE1");
    log.info(
        String.valueOf(
            reactiveWhitelistingRedisTemplate
                .keys("*")
                .flatMap(reactiveWhitelistingRedisTemplate.opsForValue()::get)));
    log.info("CASE2");
    log.info(String.valueOf(reactiveWhitelistingRedisTemplate.scan()));
    log.info("CASE3");
    log.info(String.valueOf(reactiveUserRedisTemplate.keys("*")));
    log.info("CASE4");
    log.info(reactiveWhitelistingRedisTemplate.randomKey() + "RANDOM");
    log.info("CASE5");
    log.info(String.valueOf(reactiveWhitelistingRedisTemplate.opsForValue().get("whitelisting:zenon112")));
  }
}

While getting key/keys I am always receiving empty Mono/Flux as a result like:

CASE1
FluxFlatMap
CASE2
FluxMap
CASE3
FluxMap
CASE4
MonoMapRANDOM
CASE5
MonoNext

I am convinced that Redis is not empty and example key in Redis is whitelisting:ranomuser112

To be honest I am confused about what I am doing wrong and will be grateful for suggestions on how to get the particular key from reactive Redis. Cheers!

Advertisement

Answer

I overlooked the .subscribe() method call. Without it, the reactive result was ignored. The problem has been resolved.

User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement