We want to use @Cacheable in Spring Boot with redis, and we want the redis content to be JSON so it is human readable.
This is done in our CacheConfiguration with
@Autowired
public CacheConfiguration(ObjectMapper objectMapper) {
// we need to modify the default objectMapper for redis so make a copy
this.objectMapper = objectMapper.copy()
.activateDefaultTyping(
objectMapper.getPolymorphicTypeValidator(),
ObjectMapper.DefaultTyping.NON_FINAL,
JsonTypeInfo.As.PROPERTY
);
}
@Bean
public RedisCacheManagerBuilderCustomizer redisCacheManagerBuilderCustomizer() {
RedisSerializer<Object> serializer = new GenericJackson2JsonRedisSerializer(objectMapper);
return (builder) -> builder
.withCacheConfiguration(DEFAULT_CACHE,
RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(60))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(serializer))
);
}
This adds the “@class” property to the JSON so that it can be deserialized. However, it also changes how BigDecimal is serialized. BigDecimal values become this in the JSON
"someBigDecimalProperty" : [ "java.math.BigDecimal", 11.25 ],
which looks sane enough, however it fails when fetched from the cache and is deserialized (presumably by the same ObjectMapper).
We get
[org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver] Resolved [org.springframework.data.redis.serializer.SerializationException: Could not read JSON:Cannot deserialize value of type
java.lang.String
from Array value (tokenJsonToken.START_ARRAY
) at [Source: (byte[])”{ “@class” : “com.mycompany.model.dto.MyObject”, “someBigDecimalProperty” : [ “java.math.BigDecimal”, 11.25 ], column: 26] (through reference chain: com.mycompany.model.dto.MyObject[“someBigDecimalProperty”]) ]
Why can it not deserialize what it serializes? Am I missing something in the configuration?