-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Description
I am trying to set up a Redis repository with programmatic keyspaces configuration according to https://docs.spring.io/spring-data/redis/reference/redis/redis-repositories/keyspaces.html
I would like to load the timeToLive from a configuration properties.
Problem
Here is the attempt:
@Configuration
@EnableRedisRepositories // NOT PROVIDED because using RedisMappingContext: (keyspaceConfiguration = KeyspaceConfig::class)
class RedisRepositoryConfig(
val myConfigurationProperties: MyConfigurationProperties
) {
@Bean
fun redisTemplate(redisConnectionFactory: RedisConnectionFactory?): RedisTemplate<*, *> {
val template = RedisTemplate<ByteArray?, ByteArray?>()
template.connectionFactory = redisConnectionFactory
return template
}
@Bean
fun keyValueMappingContext() =
RedisMappingContext(
MappingConfiguration(IndexConfiguration(), KeyspaceConfig(
ttl = myConfigurationProperties.redisTTLSeconds.also { println("Creating KeyspaceConfig with TTL=$it") }
))
)
}
// It does not make a difference whether this class is defined within the RedisRepositoryConfig or not
class KeyspaceConfig(
val ttl: Long,
) : KeyspaceConfiguration() {
init {
println("KeyspaceConfig constructor called with TTL=$ttl")
}
override fun initialConfiguration(): Iterable<KeyspaceSettings> =
listOf(
KeyspaceSettings(MyData::class.java, "MyHash").apply {
timeToLive = ttl.also { println("initialConfiguration(): TTL property is $ttl") }
}
)
}
@RedisHash // This annotation seems still needed
data class MyData(
@Id
val resourceId: String,
val data: String
)As opposed to the documentation, the KeyspaceSettings are not static, so we have to pass or access the configuration somehow.
- I tried the
timeToLivePropertyName = "my.config.redis-ttl-seconds"field inKeyspaceSettings, but it did not have any effect. - I tried injecting the
MyConfigurationPropertiesin theKeyspaceConfigconstructor (and using@EnableRedisRepositories(keyspaceConfiguration = KeyspaceConfig::class)) , but that doesn't work - So I tried instead passing the value in the constructor (as shown above), in the
keyValueMappingContext()bean, but it doesn't work as expected, see below
Running the application results in the following output:
Creating KeyspaceConfig with TTL=5
initialConfiguration(): TTL property is 0
KeyspaceConfig constructor called with TTL=5
This shows that KeyspaceConfig is instantiated from elsewhere, and that instance is used to call initialConfiguration() on, instead of the one that is constructed in keyValueMappingContext(), which I would expect.
Workaround
If not declaring a separate KeyspaceConfig class, but instead implement a KeyspaceConfiguration on-the-fly, it works:
@Bean
fun keyValueMappingContext() =
RedisMappingContext(
MappingConfiguration(IndexConfiguration(), object : KeyspaceConfiguration() {
override fun initialConfiguration(): Iterable<KeyspaceSettings> =
listOf(
KeyspaceSettings(MyData::class.java, "MyHash").apply {
timeToLive = myConfigurationProperties.redisTTLSeconds.also { println("initialConfiguration(): TTL is $it") }
}
)
}
))Output:
initialConfiguration(): TTL is 5
Issues
- Why does it behave in the way it does, and is this correct?
- Can the documentation be updated to show how to properly use
KeyspaceConfigwhen one needs to load properties dynamically or from configuration properties?