skip to Main Content

I’m creating 2 RespositoryConfigs with @EnableRedisRepositories and different RedisTemplate/redisTemplateRef references, however, it is always using only 1 DB.

Here some example (skipping the templates config which are using different RedisConnectionFactory and different RedisClient), and each package have only 1 repository A.class or B.class.

@Configuration
@EnableRedisRepositories(
        basePackages = "com.X.A",
        includeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = A.class),
        excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = B.class),
        redisTemplateRef = "templateA"
)
public class ARepositoryRedisConfig {

}

and

@EnableRedisRepositories(
        basePackages = "com.X.B",
        includeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = B.class),
        excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = A.class),
        redisTemplateRef = "templateB"
)
public class BRepositoryRedisConfig {

}

The repositories are CrudRepository.
Going a bit deeper, I see on registering the beans in:

org.springframework.data.redis.repository.configuration.RedisRepositoryConfigurationExtension#registerBeansForRoot

When registering the second repository I see it skips on: registerIfNotAlreadyRegistered because the first template is already registered.

Looking at other Spring-Data repository configs, it supposed to be supported.

Edit 1: How templates are configured

@Bean
public RedissonClient ARedissonClient(
        @Value("${A.redis.host}") String host,
        @Value("${A.redis.port}") String port,
        @Value("${diagnostic.app.name}") String appName,
        @Value("${redis.connectionPoolSize}") int connectionPoolSize,
        @Value("${redis.minimumIdleSize}") int connectionMinimumIdleSize,
        @Value("${redis.retryAttempts}") int retryAttempts,
        @Value("${redis.retryInterval}") int retryInterval,
        @Value("${A.redis.password:}") String password,
        @Value("${redis.timeout:6000}") int timeout,
        @Value("${redis.dns.monitoring.interval:5000}") int dnsMonitoringInterval
) {
...
}

@Bean
public RedisConnectionFactory ARedisConnectionFactory(RedissonClient ARedissonClient) {
    return new RedissonConnectionFactory(ARedissonClient);
}

@Bean(name = "templateA")
public RedisTemplate<String, String> templateA(RedisConnectionFactory ARedisConnectionFactory) {
...
}

And another one with templateB and different B.redis.host.
I tested calling the templates directly and both setups are fine, they are just not binding to the repositories, only 1 template is used for all repositories regardless what multiple EnableRedisRepositories defines.

3

Answers


  1. Chosen as BEST ANSWER

    With great help from Redis support,they pointed it requires configuring and wiring keyValueTemplateRef as well, besides only redisTemplateRef.

    So, configuration should look like:

    @Bean(name = "templateA")
    public RedisTemplate<String, String> templateA(RedisConnectionFactory ARedisConnectionFactory) {
    ...
    }
    
    @Bean(name = "templateKeyValueA")
    public KeyValueTemplate templateKeyValueA(RedisTemplate templateA) {
            return new KeyValueTemplate(
                    new RedisKeyValueAdapter(templateA),
                    new RedisMappingContext()
            );
    }
    
    @Configuration
    @EnableRedisRepositories(
            basePackages = "com.X.A",
            redisTemplateRef = "templateA",
            keyValueTemplateRef = "templateKeyValueA"
    )
    public class ARepositoryRedisConfig {
    
    }
    

    And same for BRepositoryRedisConfig and teamplateB.


  2. Make sure that the data source configuration for the two databases have different property namespace.

    //first database
    spring.datasource.jdbcUrl = [URL]
    spring.datasource.username = [username]
    spring.datasource.password = [password]
    
    //second database
    spring.second-datasource.jdbcUrl = [URL]
    spring.second-datasource.username = [username]
    spring.second-datasource.password = [password]
    

    Also if you have specified them in a properties file other than the application.properties make sure that you add @PropertySource annotation as well above your configuration class.

    @Configuration
    @PropertySource({"classpath:your-custom-property-file.properties"})
    @EnableRedisRepositories(
            basePackages = "com.X.A",
            includeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = A.class),
            excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = B.class),
            redisTemplateRef = "template"
    )
    public class ARepositoryRedisConfig {
    
    }
    

    On a different note, I think you do not have to add the include and exclude filters as the classes are in different packages.

    Login or Signup to reply.
  3. I have such a sample with connecting 2 Redis to a single Spring application (with default Lettuce), it shows which beans and bean ref need to be wired.
    https://github.com/alexvasseur/spring-twored

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search