loading...

Spring Boot with Redis conversion service and custom key converter

tech_sam profile image Sumit ・3 min read

This article is all about Spring-boot and Redis integration with using spring-data-redis.Spring Data Redis is the abstractions of the Spring Data platform to Redis the popular in-memory data structure store. The full source code for this project is available on GitHub. Let’s straight come to the point.

I am assuming that you are already familiar with spring boot and redis and you have chosen redis as a cache store for your project.

In some scenarios where we have to deal with multitenant application or we want to cache multiple user data in Redis, then to avoid data conflicts and for better app arcitecture we can take advantage of spring redis data conversion service.

Below logic is fine when we have to save the data which is common across all the users.

String cacheKey = “user-data”; 
   Cache cache = cacheManager.getCache(cacheKey);
   Cache.ValueWrapper result = cache != null ? cache.get(cacheKey) : null;
   if(result.get()!=null){
        // get the data and proceed 
    }else{
        cache.put(cacheKey, userData);
    }

But what if when you want to save individual user data then the above logic will not work. Then we can use conversion service with a custom key converter which allows us to add a dynamic prefix to user data like user id.

# Steps to integrate spring data redis

  1. add following dependencies into your build.gradle file or if it is maven then in pom.xml

compile group: ‘org.springframework.data’, name: ‘spring-data-redis’, version: ‘2.1.5.RELEASE’
compile group: ‘org.apache.commons’, name: ‘commons-pool2’, version: ‘2.0’
compile group: ‘redis.clients’, name: ‘jedis’, version: ‘2.9.3’

  1. Create a custom key and converter class like.
 @AllArgsConstructor
 public class UserCacheKey {
 private String key;
}

@Getter and @AllArgsConstructor annotations are part of Lombok project which we can cover in some other article. If you are not aware of Lombok then add default setter getter methods and constructor with a key argument.

 public class UserCacheKeyConverter implements Converter<UserCacheKey, String> {
  private UserServive userService;
  public UserCacheKeyConverter(UserServive userService) {
   this.userService = userService;
 }
 @Nullable
 @Override
 public String convert(UserCacheKey userCacheKey) {
 String userId = userService.getUserId(userCacheKey);
 return String.format(“%s_%s”, userId , userCacheKey.getKey());
 }
}
  1. Create a Redis configuration file.
@Bean(name = “userCacheManager”)
 public RedisCacheManager userCacheManager(RedisConnectionFactory 
 connectionFactory, UserService userService) {
 RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();
 DefaultFormattingConversionService conversionService = (DefaultFormattingConversionService) redisCacheConfiguration.getConversionService();
 conversionService.addConverter(UserCacheKey.class, String.class, new UserCacheKeyConverter(userService));
 redisCacheConfiguration
 .entryTtl(Duration.ofSeconds(1800)).withConversionService(conversionService)
 .disableCachingNullValues();
 return RedisCacheManager.builder(connectionFactory)
 .cacheDefaults(redisCacheConfiguration)
 .withInitialCacheConfigurations(Collections.singletonMap(“user-cache”, redisCacheConfiguration))
 .build();
 }

so here we are creating a RedisCacheManager which will handle only user cache related operations. Anywhere we can inject this RedisCacheManager as a named bean userCacheManager (@Qualifier(userCacheManager)) and perform the relevant operations like

Cache cache = userCacheManager.getCache(“user-cache”);
 UserCacheKey cacheKey = new UserCacheKey(“some-user-data”);
 Cache.ValueWrapper result = cache != null ? cache.get(cacheKey) : null;
 if(result.get()!=null){
 // get the data and proceed 
 }else{
 cache.put(cacheKey, userData);
 }

So whenever you will call cache.get method first it will call cache converter and convert the key. It will help us to abstract the cache logic and reduce complexity.

If you found this helpful or would like to chat about anything related to web or mobile development; drop a comment below. I’d love to discuss. Stay tuned for more content.

Posted on by:

tech_sam profile

Sumit

@tech_sam

A struggling & learning developer

Discussion

markdown guide