Search code examples
springspring-framework-beans

Injecting configuration dependency


I am creating a cache client wrapper using spring framework. This is to provide cache layer to our application. Right now, we are using redis. I have found out that spring-data-redis library is very good for creating my wrapper.

My application will pass a configuration POJO to my wrapper and will then use the interface that I will provide.

spring-data-redis provides an easy way to access redis using two variables.

RedisConnectionFactory
RedisTemplate<String, Object>

Although, I will be providing a better interface to my application with my interface functions like:

public Object getValue( final String key ) throws ConfigInvalidException;
public void setValue( final String key, final Object value ) throws ConfigInvalidException;
public void setValueWithExpiry(final String key, final Object value, final int seconds, final TimeUnit timeUnit) throws ConfigInvalidException;

I still want to provide RedisConnectionFactory and RedisTemplate beans.

My question is how to initialize my wrapper application with this configuration POJO?

Currently my configuration looks like this:

import java.util.List;


public class ClusterConfigurationProperties {

    List<String> nodes;
    public List<String> getNodes() {
        return nodes;
    }

    public void setNodes(List<String> nodes) {
        this.nodes = nodes;
    }
}

And my AppConfig.java looks like this:

import com.ajio.Exception.ConfigInvalidException;
import com.ajio.configuration.ClusterConfigurationProperties;
import com.ajio.validator.Validator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisClusterConfiguration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericToStringSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class AppConfig {

    @Autowired
    private ClusterConfigurationProperties clusterConfigurationProperties;
    @Autowired
    private Validator validator;

    @Bean
    ClusterConfigurationProperties clusterConfigurationProperties() {
       return null;
    }
    @Bean
    Validator validator() {
        return new Validator();
    }

    @Bean
    RedisConnectionFactory connectionFactory() throws ConfigInvalidException {
        if (clusterConfigurationProperties == null)
            throw new ConfigInvalidException("Please provide a cluster configuration POJO in context");
        validator.validate(clusterConfigurationProperties);
        return new JedisConnectionFactory(new RedisClusterConfiguration(clusterConfigurationProperties.getNodes()));
    }

    @Bean
    RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) throws ConfigInvalidException {

        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(connectionFactory());
        redisTemplate.setKeySerializer( new StringRedisSerializer() );
        redisTemplate.setHashValueSerializer( new GenericToStringSerializer<>( Object.class ) );
        redisTemplate.setValueSerializer( new GenericToStringSerializer<>( Object.class ) );

        return redisTemplate;
    }
}

Here I am expecting a ClusterConfigurationProperties POJO as a bean in application which will be using the interface of wrapper.

But to compile my wrapper, I have created a null bean itself. Then when application uses it, there will be two beans, one of application and one of wrapper.

How should I resolve this problem?


Solution

  • Actually what i wanted was to have cluster config as a bean in my client application. For that i dont need to declare @autowire clusterconfig in my wrapper application. Instead should take cluster config as a parameter in the method, so that the client will pass cluster config object when creating bean. And the bean which is created in client code should have code for creating redis connection factory.

    But all this i was writing was to make my client unknown of redis. So, better solution is to have wrapper class which takes cluster config pojo and create redis connection factory etc. And client should create this wrapper as a bean.

    Very poor concept of spring and design patterns lead me to this mistake.