Using Redis Cache with Spring Boot


In this article, we will see how to integrate Redis Cache with Spring Boot. We will learn how we can configure Redis data inside the Spring boot cache.

Let's look at the dependencies first that are required to import Redis into a Spring boot application.

Dependencies

// Adding spring-boot cache & redis dependencies
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-cache</artifactId>
   <version>2.4.3</version>
</dependency>
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-redis</artifactId>
   <version>2.4.3</version>
</dependency>

Configuration

After adding the Redis dependencies, you now need to perform some configuration so that it could be used in your project. Spring Boot will automatically configure a Redis-cache Manager but with default properties. We can modify this configuration and change it as per our requirement.

@Bean
public RedisCacheConfiguration cacheConfiguration() {
   return RedisCacheConfiguration.defaultCacheConfig()
   .entryTtl(Duration.ofMinutes(60)) // Changing the cache TTL
   .disableCachingNullValues()
   .serializeValuesWith(SerializationPair.fromSerializer(newGenericJackson2JsonRedisSerializer())); 
   //Defining serialization to retrieve data
}

Modifying the configurations gives us more control over the basic cache configuration. For example, we can change the default time-to-live values and customize the default serialization strategy to in-flight cache creation, as shown above.

Example

Let's take an example that we have an EmployeeService component that retrieves employee information from the database. Since we need to get the employee details for multiple things, we need this data to be fast which is why we are using Redis cache. Let's create an integration test for the same

@Import({ CacheConfig.class, EmployeeService.class})
@ExtendWith(SpringExtension.class)
@EnableCaching
@ImportAutoConfiguration(classes = {
   CacheAutoConfiguration.class,
   RedisAutoConfiguration.class
})
class EmployeeServiceCachingIntegrationTest {

   @MockBean
   private EmployeeRepository mockEmployeeRepository;

   @Autowired
   private EmployeeService employeeService;

   @Autowired
   private CacheManager cacheManager;

   @Test
   void
   givenRedisCaching_whenFindEmployeeById_thenEmployeeReturnedFromCache() {
      Employee employee = new Employee(id, A_DESCRIPTION);
      given(mockEmployeeRepository.findById(id))
      .willReturn(Optional.of(employee));

      Employee employeeNotFromCache = employeeService.getEmployeeById(id);
      Employee employeeFromCache = employeeService.getEmployeeById(id);

      assertThat(employeeNotFromCache).isEqualTo(employee);
      assertThat(employeeFromCache).isEqualTo(employee);

      verify(mockEmployeeRepository, times(1)).findById(id);
      assertThat(employeeFromCache()).isEqualTo(employee);
   }
}

Retrieving data from Cache

@Cacheable(value = "employeeCache")
public Employee getEmployeeForId(String id) {
   return employeeRepository.findById(id)
      .orElseThrow(RuntimeException::new);
}

We have invoked the getEmployeeById() twice. The first invocation should obtain the item from the repository, whereas the second invocation should return the same employee object from the cache without invoking the repository.

Updated on: 24-Nov-2021

5K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements