Skip to content

Spring Data Redis

codec-spring-data-redis adapts any Codec<T> to Spring Data Redis's RedisSerializer<T>, so the codec you built — with its compression and encryption — is what Redis stores.

<dependency>
    <groupId>org.jwcarman.codec</groupId>
    <artifactId>codec-spring-data-redis</artifactId>
</dependency>

RedisTemplate

RedisTemplate<String, Person> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
template.setKeySerializer(RedisSerializer.string());
template.setValueSerializer(CodecRedisSerializer.of(codecFactory, Person.class));

CodecRedisSerializer.of takes a Codec<T>, a codec plus its type, or a CodecFactory plus the type. RedisSerializer's contract treats null as absent — it is handed null on a miss — so the codec is wrapped with nullSafe(); every other value and exception passes through unchanged.

The cache abstraction

Spring's cache abstraction wants a serialization pair rather than a serializer:

RedisCacheConfiguration.defaultCacheConfig()
    .serializeValuesWith(CodecRedisSerializer.of(codecFactory, Person.class).serializationPair());

Auto-configuration

The cache auto-configuration activates when all of the following are true:

  • codec-spring-data-redis and the starter are on the classpath
  • spring-boot-starter-cache is on the classpath, and @EnableCaching is set
  • spring-boot-starter-data-redis is on the classpath
  • a CodecFactory bean is present — which a backend module and the starter give you
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

Once all four hold, the auto-configured CodecFactory serializes cache values for the caches you name:

codec.redis.cache.caches.people=com.example.Person
codec.redis.cache.caches.orders=com.example.OrderSummary

Cache values are heterogeneous but a codec is typed, which is why each cache names its value type — a JSON backend asked to decode to Object would hand back a Map, not a Person. Caches not listed keep Spring Boot's default serializer; every other setting (TTL, key prefix, key serializer) is preserved.

A backend whose format is self-describing can serve every cache from one codec. Apache Fory writes the class into each payload, so with a Fory bean in place:

codec.redis.cache.default-type=java.lang.Object

Set codec.redis.cache.enabled=false to switch the auto-configuration off.

Properties reference

Property Type Default Meaning
codec.redis.cache.enabled boolean true Whether codec serializes Redis cache values.
codec.redis.cache.default-type class name unset Value type for caches not listed under caches; unset leaves them on Spring Boot's default serializer.
codec.redis.cache.caches.<name> class name (none) Value type for the named cache.

Compress, encrypt, cache

The pipeline this was built for — a CodecFactory bean whose codecs compress and encrypt — needs nothing Redis-specific:

@Bean
CodecFactory codecFactory(ObjectMapper mapper, DataKeyProvider keys) {
    CodecFactory json = new JacksonCodecFactory(mapper);
    EnvelopeCodec envelope = EnvelopeCodec.builder(keys).build();
    return new CodecFactory() {
        @Override
        public <T> Codec<T> create(TypeRef<T> type) {
            return json.create(type).andThen(new ZstdCodec()).andThen(envelope);
        }
    };
}

Every cache named in codec.redis.cache.caches now holds compressed, authenticated ciphertext.

Where next

  • Spring Boot — the starter and auto-configuration this page's cache support builds on
  • Codec Composition — nullSafe(), used here to match Redis's "null on a miss" contract
  • Handling Failures — what CodecException through a CacheErrorHandler means for a cache read