Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ClassCastException in Spring Redis Cache

I'm developing a Spring Boot application with Spring Boot version 2.1.8.RELEASE. I need to build custom RedisCacheManager.

RedisCacheManager is as follows.

@EnableCaching
@Configuration
class CacheConfig {
    @Bean
    fun redisCacheManager(lettuceConnectionFactory: RedisConnectionFactory): RedisCacheManager? {
        val redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
            .entryTtl(Duration.ofHours(1))

        return RedisCacheManager.RedisCacheManagerBuilder
            .fromConnectionFactory(lettuceConnectionFactory)
            .cacheDefaults(redisCacheConfiguration)
            .build()
    }
}

In my service, I cache response with @Cacheble. See:

@Cacheable(cacheNames = ["cached_sample"])
    fun getAllSample(): List<SampleRecord> {
        return auditableRepository.findAll()
    }

Model I cached:

data class SampleRecord(
    @ApiModelProperty(readOnly = true)
    val id: Long? = null,
    @ApiModelProperty(readOnly = true)
    val active: Boolean? = null,
    @ApiModelProperty(readOnly = true)
    val createdDate: Instant? = null,
    val param: String
): Serializable

When I call function second time, I get following exception

Caused by: java.lang.ClassCastException: com.cryptocurrency.exchange.sample.model.SampleRecord cannot be cast to com.cryptocurrency.exchange.sample.model.SampleRecord

What whould be the reason of this exception?

like image 577
T. Ç Avatar asked Aug 29 '26 20:08

T. Ç


1 Answers

This issue occurs if you Spring dev-tools in your dependency tree. There is a fairly easy solution, but it isn't documented well. You need to set the Redis cache config to reference the Context classloader when deserializing objects. For your code, it would look like:

redisCacheConfiguration = RedisCacheConfiguration
.defaultCacheConfig(Thread.currentThread().getContextClassLoader())
.entryTtl(Duration.ofHours(1))

The .defaultCacheConfig(Thread.currentThread().getContextClassLoader()) makes sure that Redis has a reference to the Context classloader when deserializing. Spring outlines this in the Known Issues sections here: https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#using-boot-devtools-known-restart-limitations

like image 101
MattC Avatar answered Sep 01 '26 18:09

MattC



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!