AwesomeTown
AwesomeTown

Reputation: 2880

Multiple RedisConnectionFactories in Spring Boot Application

My application uses one "main" redis instance for things like session storage and cache but needs to talk to a separate "external" instance for other reasons. I am trying to determine the "best" ("most idiomatic"? "simplest"?) way to configure this in my Spring Boot application.

Ideally I'd just like to use the default auto-configuration for the main instance but as soon as I register a connection factory for the external instance the @ConditionalOnMissngBean({RedisConnectionFactory.class}) condition in LettuceConnectionConfiguration becomes false and so the default instance isn't created. Looking at what else is going on in LettuceConnectionConfiguration etc. I feel like I'd rather not manually configure it if I don't need to.

I could just not expose the "external" connection factory as a bean and only use it internally to create the beans that depend on it but, while that would be ok in my specific case, I'd like to understand if there's a better solution where both factories can be exposed.

Is there some way I can expose the second RedisConnectionFactory without disabling the default one provided by auto configuration? Is there a clear "right way" to do this sort of thing?

Upvotes: 4

Views: 4241

Answers (1)

clevertension
clevertension

Reputation: 7077

you must implement the BeanDefinitionRegistryPostProcessor to adjust the RedisConnectionFactory order

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.stereotype.Component;

@Component
public class MultipleRedisConnectionFactoryRegistrar implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        BeanDefinition bd1 = registry.getBeanDefinition("redisConnectionFactory");
        if (bd1 != null) {
            BeanDefinition bd = new RootBeanDefinition(ExternalRedisConnectionFactoryBean.class);
            registry.registerBeanDefinition("externalRedisConnectionFactory", bd);
        }
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

    }
}

in ExternalRedisConnectionFactoryBean, you can create your own RedisConnectionFactory

import org.springframework.beans.factory.FactoryBean;
import org.springframework.data.redis.connection.RedisConnectionFactory;

public class ExternalRedisConnectionFactoryBean implements FactoryBean<RedisConnectionFactory> {
    @Override
    public RedisConnectionFactory getObject() throws Exception {
        //you can mannually create your external redis connection factory here
        return null;
    }

    @Override
    public Class<?> getObjectType() {
        return RedisConnectionFactory.class;
    }
}

if you want to use the multiple RedisConnectionFactory, you @Qualifier is the right choice, for example

@Autowired
@Qualifier("redisConnectionFactory")
private RedisConnectionFactory defaultRedisConnectionFactory;

@Autowired
@Qualifier("externalRedisConnectionFactory")
private RedisConnectionFactory externalRedisConnectionFactory;

Upvotes: 1

Related Questions