Search code examples
javaspring-bootcachingspring-data-redis

Distributed redis cache in spring boot micro services


I have two micro services. Item micro service populates the data to redis cache. It is successful and I am able to retrieve the data as well in the same micro service. Another micro service is Order service. In order service I need to fetch the item service data from redis cache as I need to make use of distributed caching. However I am not able to access cache data in order service from redis cache.

Here is my implementation code

Item Service

RedisConfig.java

@Configuration
public class RedisConfig {

    /** The redis host name. */
    @Value("${spring.redis.host}")
    private transient String redisHostName;

    /** The redis port. */
    @Value("${spring.redis.port}")
    private transient int redisPort;

    /**
     * Jedis connection factory.
     *
     * @return the jedis connection factory
     */
    @Bean
    public JedisConnectionFactory jedisConnectionFactory() {
        final RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(redisHostName,
                redisPort);
        return new JedisConnectionFactory(redisStandaloneConfiguration);
    }

    /**
     * Redis template.
     *
     * @return the redis template
     */
    @Bean
    public RedisTemplate<String, ItemEntity> redisTemplate() {
        final RedisTemplate<String, ItemEntity> template = new RedisTemplate<>();
        template.setConnectionFactory(jedisConnectionFactory());
        return template;
    }
}

RedisRepoImpl.java

 /** The redis template. */
    private transient RedisTemplate<String, ItemEntity> redisTemplate;

    /** The hash operations. */
    private transient HashOperations<String, Long, ItemEntity> hashOperations;
    
    /** The Constant CACHE_KEY. */
    private static final String CACHE_KEY ="ITEM_MASTER";


    public RedisRepositoryImpl(final RedisTemplate<String, ItemEntity> redisTemplate) {
        this.redisTemplate = redisTemplate;
        this.hashOperations = redisTemplate.opsForHash();
    }


    @Override
    public void save(final ItemEntity item) {
        hashOperations.put(CACHE_KEY, item.getItemEntityId(), item);
    }

    /**
     * Find all.
     *
     * @return the map
     */
    @Override
    public List<ItemEntity> findAll() {
        final Map<Long, ItemEntity> itemEntities = hashOperations.entries(CACHE_KEY);
        return new ArrayList<>(itemEntities.values());
    } 

    //other code

OrderService

RedisConfig.java

I have created ItemEntity class in Order service as well same as Item Service.

@Configuration
public class RedisConfig {
    
    /** The redis host name. */
    @Value("${spring.redis.host}")
    private transient String redisHostName;

    /** The redis port. */
    @Value("${spring.redis.port}")
    private transient int redisPort;

    /**
     * Jedis connection factory.
     *
     * @return the jedis connection factory
     */
    @Bean
    public JedisConnectionFactory jedisConnectionFactory() {
        final RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(redisHostName,
                redisPort);
        return new JedisConnectionFactory(redisStandaloneConfiguration);
    }

    /**
     * Redis template.
     *
     * @return the redis template
     */
    @Bean
    public RedisTemplate<String, ItemEntity> redisTemplate() {
        final RedisTemplate<String, ItemEntity> template = new RedisTemplate<>();
        template.setConnectionFactory(jedisConnectionFactory());
        template.setKeySerializer(new StringRedisSerializer());
        template.setHashKeySerializer(new GenericToStringSerializer<Long>(Long.class));
        template.setHashValueSerializer(new GenericToStringSerializer<ItemEntity>(ItemEntity.class));
        return template;
    }

RedisRepoImpl.java

@Repository
public class RedisRepositoryImpl implements RedisRepository {
    
    /** The Constant CACHE_KEY. */
    private static final String CACHE_KEY ="ITEM_MASTER";

    /** The hash operations. */
    private transient HashOperations<String, Long, ItemEntity> hashOperations;

    /**
     * Instantiates a new redis repository impl.
     *
     * @param redisTemplate the redis template
     */
    public RedisRepositoryImpl(final RedisTemplate<String, ItemEntity> redisTemplate) {
        this.hashOperations = redisTemplate.opsForHash();
    }

    /**
     * Find all.
     *
     * @return the map
     */
    @Override
    public List<ItemEntity> findAll() {
        final Map<Long, ItemEntity> itemEntities = hashOperations.entries(CACHE_KEY);
        return new ArrayList<>(itemEntities.values());
    }
}

I am getting cache as empty list in order service. Could you please tell me what mistake I am doing here.


Solution

  • I was able to solve this after going through few more online materials.

    The additional change I did is updated the RedisTemplate bean in both the micro services as follows

        @Bean
        public RedisTemplate<String, ItemEntity> redisTemplate() {
            final RedisTemplate<String, ItemEntity> template = new RedisTemplate<>();
            template.setConnectionFactory(jedisConnectionFactory());
            Jackson2JsonRedisSerializer<ItemEntity> values = new Jackson2JsonRedisSerializer<>(ItemEntity.class);
            ObjectMapper objectMapper = new ObjectMapper();
            objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
            objectMapper.registerModule(new JavaTimeModule());
            objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
            values.setObjectMapper(objectMapper);
            template.setHashValueSerializer(values);
            return template;
        }