twiechert
twiechert

Reputation: 83

Spring Boot - Autowire component using different profiles

I have a component EmbeddedRedis that depends on a configuration object RedisConfig parsed from the application's property file. There are different property files, corresponding to the possible application profiles that can be run. Thus, when run in profile master, the component EmbeddedRedis will be provisioned according to the master profile.

In a test class, that is supposed to set-up a local Redis cluster, I also require Redis objects provisioned according to all other profiles. I sketched my idea below using the @Qualifier annotation, which does not bring the desired result.

@Autowired @Qualifier("dev-cluster-master")
private Redis embeddedRedisMaster;

@Autowired @Qualifier("dev-cluster-slave-001")
private Redis embeddedRedisSlave1;

@Autowired @Qualifier("dev-cluster-slave-002")
private Redis embeddedRedisSlave2;

How can I archive the desired result in Spring Boot? If that doesn't work directly, would it also suffice to obtain the before-mentioned configuration objects parsed from the different property files.

@Component
@ConfigurationProperties(prefix = "spring.redis")
public class RedisConfig {
 ....
}

Thanks in advance!

Upvotes: 1

Views: 9086

Answers (3)

dhalfageme
dhalfageme

Reputation: 1545

If you need your component only with certain profile and you don't want to or can't create a common interface you could inject like this:

@Autowired
    private Optional< Redis > redis;

You would have to check if present on each different object on every profile.

If you share a common interface use the other answer solution to create different beans implementing the interface per each profile.

Upvotes: 1

You can do something like this: Consider you have an interface definition:

public interface SomeService {
    String someMethod;
}

And two implemented class:

@Profile("production")
@Service
public class SomeServiceProd implements SomeService {
     @Override String someMethod() {return "production";}
}

@Profile("development")    
@Service
public class SomeServiceProd implements SomeService {
     @Override String someMethod() {return "development";}
}

And use this service in test and main code:

@Autowired SomeService service;

Upvotes: 2

Afridi
Afridi

Reputation: 6932

You can do something like this: Consider you have a class definition (Redis in your example)

public class CustomService {

    private String name;

    public CustomService(String name){
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

And a configuration class like:

@Configuration
public class Config {

    @Bean
    @Profile("master")
    CustomService serverConfig1(){
        CustomService service1 = new CustomService("master");
        return service1;
    }

    @Bean
    @Profile("slave")
    CustomService serverConfig2(){
        CustomService service1 = new CustomService("slave");
        return service1;
    }
}

which initiate 2 different objects based on current active profile. If current active profile is "master", then serverConfig1() will get executed, otherwise serverConfig2().

And finally autowired your service/object like this:

@Autowired
CustomService service;

This will depends on above executed bean definition in configuration file.

And property file should look like this:

spring.profiles.active=slave

So in this example, after executing above code, the value of 'name' in CustomService service; will be "slave" instead of "master", because current active profile is "slave" and thus "serverConfig2()" will get executed

Upvotes: 3

Related Questions