[Home](../README.md) | Prev: [TTL](08-ttl.md) | Next: [Production checklist](10-production-checklist.md) # 9. Redis as the Spring cache The annotations (`@Cacheable`, `@CacheEvict`, keys, the self-invocation trap) are covered in [The Spring Cache Abstraction](https://ankurm.com/spring-cache-abstraction-cacheable-cacheevict-self-invocation-trap/) and its [companion project](../../caching). This chapter is only about what changes when the cache is Redis. With `spring-boot-starter-cache` and the Redis starter on the classpath and `@EnableCaching`, Boot picks `org.springframework.data.redis.cache.RedisCacheManager` ([14-cache-default.txt](output/14-cache-default.txt)). [UserService](../src/main/java/com/ankurm/redis/cache/UserService.java) has two cached methods that differ only in whether the result is `Serializable`. ## What the defaults store Keys are readable: `::`, here `legacy::1`. The value is JDK-serialised, exactly as in [chapter 2](02-default-serialization.md): ``` $ redis-cli -p 6390 --no-raw GET legacy::1 "\xac\xed\x00\x05sr\x00'com.ankurm.redis.model.SerializableUser..." ``` `spring.cache.redis.time-to-live=10m` works: `TTL legacy::1` is `600`. A result that is **not** `Serializable` is not cached, and the *method call fails*: ``` java.lang.IllegalStateException message: Cannot serialize value of type com.ankurm.redis.model.User without a serializer method body ran 2 time(s) in total ``` The body ran (twice in total: once for the good call, once for the failing one), the write to Redis threw, and the caller sees the exception. A `@Cacheable` on a method returning a non-Serializable type breaks that method. ## Switching to JSON Declare a `RedisCacheConfiguration` bean. [JsonCacheConfig](../src/main/java/com/ankurm/redis/config/JsonCacheConfig.java) (active under the `json-cache` profile) does it with the same allow-listed Jackson 3 serializer as [chapter 4](04-json-serializers.md) ([15-cache-json.txt](output/15-cache-json.txt)): ``` $ redis-cli -p 6390 GET users::1 {"@class":"com.ankurm.redis.model.User","id":1,"name":"Ankur"} ``` The non-Serializable record now caches, and the method body ran once for two calls. ## The property that stops applying The test sets `spring.cache.redis.time-to-live=10m` **and** declares a bean with `entryTtl(Duration.ofMinutes(5))`. The key's TTL is `300`. When you define your own `RedisCacheConfiguration`, Boot used that bean and the `spring.cache.redis.time-to-live` property had no effect on the TTL. Put the TTL in the bean. ## Going deeper - [RedisCacheDefaultTest](../src/test/java/com/ankurm/redis/RedisCacheDefaultTest.java) and [RedisCacheJsonTest](../src/test/java/com/ankurm/redis/RedisCacheJsonTest.java) - [Spring Boot: Caching, Redis](https://docs.spring.io/spring-boot/reference/io/caching.html#io.caching.provider.redis) - [Spring Data Redis: Redis Cache](https://docs.spring.io/spring-data/redis/reference/redis/redis-cache.html) [Home](../README.md) | Prev: [TTL](08-ttl.md) | Next: [Production checklist](10-production-checklist.md)