Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Resolving Redis Serialization Issues in Spring Boot

Tech May 8 4

To integrate Redis into a Spring Boot application, start by including the necessary dependencies in your pom.xml file. The spring-boot-starter-data-redis provides the core integration, while jackson-databind is required for JSON serialization capabilities.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
</dependency>

By default, Spring Boot uses JDK serialization for Redis values, which results in binary data that is hard to read. To store data in a human-readable JSON format, you must configure a custom RedisTemplate bean. The following configuration class sets up a Jackson2JsonRedisSerializer for value serialization and a StringRedisSerializer for keys.

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisCacheConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);

        // Use Jackson2JsonRedisSerializer to serialize values
        Jackson2JsonRedisSerializer<Object> Serializer = new Jackson2JsonRedisSerializer<>(Object.class);

        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        Serializer.setObjectMapper(objectMapper);

        // String serializer for keys
        StringRedisSerializer stringSerializer = new StringRedisSerializer();

        template.setKeySerializer(stringSerializer);
        template.setValueSerializer(Serializer);
        template.setHashKeySerializer(stringSerializer);
        template.setHashValueSerializer(Serializer);

        template.afterPropertiesSet();
        return template;
    }
}

With the configuration in place, create a service component to interact with the Redis database. This service encapsulates the RedisTemplate to perform standard operations like saving, retrieving, and deleting data.

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

@Component
public class CacheService {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    public void save(String key, Object data) {
        redisTemplate.opsForValue().set(key, data);
    }

    public Object retrieve(String key) {
        return redisTemplate.opsForValue().get(key);
    }

    public void remove(String key) {
        redisTemplate.delete(key);
    }
}

Below is a test case verifying the serialization logic. It writes a string value to Redis and reads it back.

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class RedisApplicationTests {

    @Autowired
    private CacheService cacheService;

    @Test
    public void testRedisOperations() {
        String key = "username";
        String value = "adminUser";
        
        cacheService.save(key, value);
        System.out.println("Retrieved value: " + cacheService.retrieve(key));
    }
}

A critical aspect of this configuration is handling data consistency. When RedisTemplate is configured with a JSON serializer, it writes objects into the database as JSON strings, often including type metadata. If you attempt to retrieve a key using this template that was manually set via a Redis client (e.g., using SET key "plain_text"), the deserialization process will fail. The Jackson parser expects a JSON structure but encounters a raw string, leading to a JsonParseException: Unrecognized token. Therefore, ensure that data read by the application was originally serialized by the same serialization logic to avoid runtime errors.

Tags: Spring Boot

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.