I've a Spring Boot application with different Profile setup : dev
, prod
, qc
, console
etc.
The two configuration classes are setup as follows. MyConfigurationA
should be registered for all profiles except console
. MyConfigurationB
should be registered except for console
and dev
.
When I run the application with profile console
, the MyConfigurationA
doesn't get registered - which is fine. But MyConfigurationB
gets registered - which I do not want. I've setup the @Profile
annotation as follows to not register the MyConfigurationB
for profile console
and dev
.
But the MyConfigurationB
is getting registered when I run the application with profile console
.
@Profile({ "!" + Constants.PROFILE_CONSOLE , "!" + Constants.PROFILE_DEVELOPMENT })
The documentation ( http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/annotation/Profile.html) has an example of including one profile and excluding the other. In my example I'm excluding both as @Profile({"!p1", "!p2"}):
@Profile({"p1", "!p2"}), registration will occur if profile 'p1' is active OR if profile 'p2' is not active.
My question is : How can we skip registration of the configurations of both profiles? @Profile({"!p1", "!p2"})
is doing OR operation. We need AND operation here.
The code :
@Configuration
@Profile({ "!" + Constants.PROFILE_CONSOLE })
public class MyConfigurationA {
static{
System.out.println("MyConfigurationA registering...");
}
}
@Configuration
@Profile({ "!" + Constants.PROFILE_CONSOLE , "!" + Constants.PROFILE_DEVELOPMENT }) // doesn't exclude both, its OR condition
public class MyConfigurationB {
static{
System.out.println("MyConfigurationB registering...");
}
}
public final class Constants {
public static final String PROFILE_DEVELOPMENT = "dev";
public static final String PROFILE_CONSOLE = "console";
...
}
@Profile({"!console", "!dev"})
means (NOT console) OR (NOT dev) which is true if you run your app with the profile 'console'.
To solve this you can create a custom Condition:
public class NotConsoleAndDevCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
Environment environment = context.getEnvironment();
return !environment.acceptsProfiles("console", "dev");
}
}
And apply the condition via the @Conditional annotation to the Configuration:
@Conditional(NotConsoleAndDevCondition.class)
public class MyConfigurationB {