Reputation: 103
My controller uses a redis template to get and set data from redis
val redisTemplate: RedisTemplate<String, Game>
The template is injected using a bean
@Bean
fun <T> redisTemplate(builder: RestTemplateBuilder): RedisTemplate<String, T> {
val serializer = Jackson2JsonRedisSerializer(Game::class.java)
serializer.setObjectMapper(objectMapper)
val template = RedisTemplate<String, T>()
template.setConnectionFactory(connectionFactory())
template.setDefaultSerializer(serializer)
return template
}
This works however I have had to be explicit about the top level class being serialized and therefore the template returned will only work for RedisTemplate<String, Game>
and not for RedisTemplate<String, T>
.
I have tried changing the serializer instantiation to the following but it doesn't compile.
val serializer = Jackson2JsonRedisSerializer(T::class.java)
I have tried changing it to the following
val serializer = Jackson2JsonRedisSerializer(Object::class.java)
This compiles but I get an exception when reading from redis
java.lang.ClassCastException: class java.util.LinkedHashMap cannot be cast to class com.noicesoftware.redis.model.Game (java.util.LinkedHashMap is in module java.base of loader 'bootstrap'; com.noicesoftware.redis.model.Game is in unnamed module of loader 'app')
I have tried using GenericJackson2JsonRedisSerializer but I get the behaviour and exception as above.
val serializer = GenericJackson2JsonRedisSerializer(objectMapper)
Any thoughts would be greatly appreciated. The full code is available here; https://github.com/DangerousDarlow/springboot-redis
Upvotes: 2
Views: 4809
Reputation: 103
I haven't been able to find a solution to keep the bean generic. If I make the type reified then I must also make the function inline which and then either private or final. This causes runtime errors. My solution is to move the generic code into a private inline function and then declare a bean for each template type I want. Not as neat as I had hoped but it's not too bad I suppose.
private inline fun <reified T> getRedisTemplate(): RedisTemplate<String, T> {
val serializer = Jackson2JsonRedisSerializer(T::class.java)
serializer.setObjectMapper(objectMapper)
val template = RedisTemplate<String, T>()
template.setConnectionFactory(connectionFactory())
template.setDefaultSerializer(serializer)
return template
}
@Bean
fun redisTemplate(): RedisTemplate<String, Game> = getRedisTemplate()
Upvotes: 2