Arnab Das
Arnab Das

Reputation: 153

Rule out beans governed by Multiple spring @Profiles at same time

Can I control whether a Spring bean in my application context is instantiated based on the parameter I pass to the application?

Example:

If I have spring profiles set in

ANT's build.xml jvmarg as: -Dspring.profiles.active=P1,P2

For the below code snippet in a Configuration class:

@Bean
@Profile({"!P1", "!P2"})
public String P3() {
    String s = "Check1:P3";
    System.out.println(s);
    return s;
}

@Bean
@Profile({"!P1", "!P3"})
public String P2() {
    String s = "Check2:P2";
    System.out.println(s);
    return s;
}


@Bean
@Profile({"!P2", "!P3"})
public String P1() {
    String s = "Check3:P1";
    System.out.println(s);
    return s;
}

@Bean
@Profile("P3")
public String P3_1() {
    String s = "Check4:P3";
    System.out.println(s);
    return s;
}

@Bean
@Profile("P1")
public String P1_1() {
    String s = "Check5:P1";
    System.out.println(s);
    return s;
}
@Bean
@Profile("P2")
public String P2_1() {
    String s = "Check6:P2";
    System.out.println(s);
    return s;
}

I get the output as:

Check2:P2
Check3:P1
Check5:P1
Check6:P2

which is correct.

But when I set the profiles in build.xml as:

-Dspring.profiles.active=P1

Output:
Check1:P3
Check2:P2
Check3:P1
Check5:P1

But as per my expectation, I was hoping to get as output like:

Check3:P1
Check5:P1

(i.e.) only P1() bean is up at runtime.

Can anyone suggest me if that is possible with @Profiles ? I can control the beans which are up at runtime based on the exclusion rule of profiles? Or how can I achieve this?

The basic requirement is if there are 'n' beans. I can control 1 bean to be up at runtime based on the parameter I pass to the environment/server target.

I am trying to make use of a shared code(where all beans are defined) which can be used by different environments(requiring one bean each to up for a particular environment)?

Upvotes: 1

Views: 956

Answers (2)

Arnab Das
Arnab Das

Reputation: 153

I was able to able to solve the problem of on-demand bootstrapping of my application serving various business through a shared orchestrating code base by blending the concept of ServiceLocatorFactoryBean and Spring Profiles.

Links: http://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/beans/factory/config/ServiceLocatorFactoryBean.html http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-profiles.html

Spring profiles helped in creating the beans on demand as specified in the environment/application context and locator factory creating a dynamic proxy which implements that interface, delegating to an underlying BeanFactory, hence decoupling of calling code from the BeanFactory API, by using an appropriate custom locator interface

Upvotes: 0

Alexander
Alexander

Reputation: 2878

Probably profiles are not good for this.

You might use just ordinary properties instead.

Check @Conditional annotation (Spring 4) and even more handy @ConditionalOnExpression("${P1}") (available in Spring boot only).

Another option - some manual logic inside your @Configuration class, e.g.:

@Value("${P1}") boolean isP1;

@Bean String p1OrP2() {
    return (isP1) ? "P1" : "P2";
}

This might be enough for common cases, e.g. this way you can control whether to use some feature (use a full implementation bean) or not (use some bean with a minimal behavior).

Upvotes: 1

Related Questions