0
votes

Am using spring-data-redis(2.1.5.RELEASE) and jedis(2.10.2) client to connect to my azure redis instance from different services running as spring-boot application.

Two services has the same caching methods and pointed to the same cache by implementing the following configuration. The problem am facing is when one service trying to read a cached value created by another service, de-seralization exception occurs.

Exception:

org.springframework.data.redis.serializer.SerializationException: Cannot deserialize; nested exception is org.springframework.core.serializer.support.SerializationFailedException: Failed to deserialize payload. Is the byte array a result of corresponding serialization for DefaultDeserializer?; nested exception is org.springframework.core.NestedIOException: Failed to deserialize object type; nested exception is java.lang.ClassNotFoundException

Note: Am using redis only to cache the data read from my database.

Redis Cache Configuration of microservice 1

public RedisCacheWriter redisCacheWriter(RedisConnectionFactory connectionFactory) {
    return RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory);
}

@Bean
public RedisCacheManager cacheManager() {
    Map<String, RedisCacheConfiguration> cacheNamesConfigurationMap = new HashMap<>();
    cacheNamesConfigurationMap.put("employers", RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofSeconds(90000)));
    cacheNamesConfigurationMap.put("employees", RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofSeconds(90000)));

    RedisCacheManager manager = new RedisCacheManager(redisCacheWriter(), RedisCacheConfiguration.defaultCacheConfig(), cacheNamesConfigurationMap);
    manager.setTransactionAware(true);
    manager.afterPropertiesSet();

    return manager;
}

Redis Cache Configuration of microservice 2

public RedisCacheWriter redisCacheWriter(RedisConnectionFactory connectionFactory) {
    return RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory);
}

@Bean
public RedisCacheManager cacheManager() {
    Map<String, RedisCacheConfiguration> cacheNamesConfigurationMap = new HashMap<>();
    cacheNamesConfigurationMap.put("employees", RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofSeconds(90000)));

    RedisCacheManager manager = new RedisCacheManager(redisCacheWriter(), RedisCacheConfiguration.defaultCacheConfig(), cacheNamesConfigurationMap);
    manager.setTransactionAware(true);
    manager.afterPropertiesSet();

    return manager;
}

Caching methods in both services

@Cacheable(value = "employees", key = "#employeesId") public Employee getEmployee(String employeesId) { //methods }

Employee class in both services

public class Employee implements Serializable { private String id; private String name; }

1
can you post the exact exception that you're getting? - Muhammad Inshal
@MuhammadInshal I have added the exception am facing. - Venkat
@Venkat are these two separate applications or is it the same application deployed twice? - Jerome
@Jerome these two are separate applications and if deploy the same application twice, service is able to read read the cached data(which is created by that service) - Venkat
Found the issue. Had Employee.java in different packages - Venkat

1 Answers

0
votes

I would suggest you make sure the Employee classes are identical and then add a serialVersionUID field to the classes. Clear the Redis cache and try again.

This is from the Javadocs in the java.io.Serializable interface:

If a serializable class does not explicitly declare a serialVersionUID, then the serialization runtime will calculate a default serialVersionUID value for that class based on various aspects of the class, as described in the Java(TM) Object Serialization Specification. However, it is strongly recommended that all serializable classes explicitly declare serialVersionUID values, since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations, and can thus result in unexpected InvalidClassExceptions during deserialization. Therefore, to guarantee a consistent serialVersionUID value across different java compiler implementations, a serializable class must declare an explicit serialVersionUID value. It is also strongly advised that explicit serialVersionUID declarations use the private modifier where possible, since such declarations apply only to the immediately declaring class--serialVersionUID fields are not useful as inherited members.