Spring @ConditionalOnProperty havingValue = "value1" or "value2"
Solution 1
Spring Boot provides AnyNestedCondition
for created a condition that will match when any nested condition matches. It also provides AllNestedConditions
and NoneNestedConditions
for matching when all nested conditions or no nested conditions match respectively.
For your specific case where you want to match a value of value1
or value2
you would create an AnyNestedCondition
like this:
class ConfigNameCondition extends AnyNestedCondition {
public ConfigNameCondition() {
super(ConfigurationPhase.PARSE_CONFIGURATION);
}
@ConditionalOnProperty(name = "test.configname", havingValue = "value1")
static class Value1Condition {
}
@ConditionalOnProperty(name = "test.configname", havingValue = "value2")
static class Value2Condition {
}
}
And then use it with @Conditional
, like this for example:
@Bean
@Conditional(ConfigNameCondition.class)
public SomeBean someBean() {
return new SomeBean();
}
As shown in the javadoc for the nested condition annotations (linked to above) the nested conditions can be of any type. There's no need for them to all be of the same type as they are in this particular case.
Solution 2
The annotations @ConditionalOnProperty
and @ConditionalOnExpression
both do NOT have the java.lang.annotation.Repeatable
annotation so you would not be able to just add multiple annotations for checking multiple properties.
The following syntax has been tested and works:
Solution for Two Properties
@ConditionalOnExpression("${properties.first.property.enable:true} && ${properties.second.property.startServer:false}")
Note the following:
- You need to using colon notation to indicate the default value of the property in the expression language statement
- Each property is in a separate expression language block ${}
- The && operator is used outside of the SpEL blocks
It allows for multiple properties that have differing values and can extend to multiple properties.
If you want to check more then 2 values and still maintain readability, you can use the concatenation operator between different conditions you are evaluating:
Solution for more then 2 properties
@ConditionalOnExpression("${properties.first.property.enable:true} " +
"&& ${properties.second.property.enable:true} " +
"&& ${properties.third.property.enable:true}")
The drawback is that you cannot use a matchIfMissing argument as you would be able to when using the @ConditionalOnProperty
annotation so you will have to ensure that the properties are present in the .properties or YAML files for all your profiles/environments or just rely on the default value
Taken from here Spring Boot SpEL ConditionalOnExpression check multiple properties
Solution 3
I am looking for
configurationOnProperty
usage where I can specify to consider more than one value
You can use Condition interface of Spring 4.0
.
This interface has a method matches(...)
which you can use.
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
public class TestCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
String testValue = (context.getEnvironment().getProperty("test.configname");
return "value1".equalsIgnoreCase("testValue") || "value2".equalsIgnoreCase("testValue");
}
}
And then use TestCondition
inside your @Configuration
like below :
@Configuration
public class TestConfig {
@Conditional(value=TestCondition .class)
public MyBean getTestConfigBean() {
//TODO YOUR CODE;
}
}
I would like to know if it is possible to specify confiugrationOnProperty with condition of havingValue != "value3"
public class TestCondition2 implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
String testValue = (context.getEnvironment().getProperty("test.configname");
return ! "value3".equalsIgnoreCase("testValue");
}
}
And then use it like this :
@Configuration
public class TestConfig {
@Conditional(value=TestCondition2 .class)
public MyBean getTestConfigBean() {
//TODO YOUR CODE;
}
}
Comments
-
MLS almost 4 years
I am looking for
configurationOnProperty
usage where I can specify to consider more than one value as shown belowEg:
@ConditionalOnProperty(value = "test.configname", havingValue = "value1" or "value2")
OR
I would like to know if it is possible to specify
confiugrationOnProperty
with condition ofhavingValue != "value3"
Eg:
@ConditionalOnProperty(value = "test.configname", havingValue != "value3")
Please let me know if there is a way to achieve any one of the above in
spring boot
configuration.-
Azarea almost 6 years
-
-
gstackoverflow almost 5 yearsit looks awful. Do you have ticket to make @ConditionalOnProperty repeatable ?
-
Andy Wilkinson almost 5 yearsYes. It's not that easy to implement though as some will want AND semantics and others will want OR. Nested conditions may not be aesthetically pleasing, but
AnyNestedCondition
,AllNestedConditions
andNoneNestedConditions
give you a lot of flexibility. -
gstackoverflow almost 5 yearsIt is flexible but not user friendly)
-
gstackoverflow almost 5 yearsYou have the same logic(AND) for @Qualifier and everyone is happy
-
Andy Wilkinson almost 5 yearsEveryone apart from the person who asked this question and wanted
OR
, hence the use ofAnyNestedCondition
above. -
gstackoverflow almost 5 yearsBut why don't make it consistent with @Qualifier? It is a mess from my view
-
Andy Wilkinson almost 5 yearsThe issue that I've linked to above has not been declined and, if you read it, you'll see that a change to Spring Framework would also be required. Rather than making a series of derogatory remarks, perhaps you'd like to do something constructive and contribute some pull requests?
-
gstackoverflow almost 5 yearsAndy, sorry. I didn't want you to be upset. I just wanted to emphasize that it is to complex for framework client. I don't know so much about BPPs and BFPPs and other internal spring framework stuff so I am afraid I won't suggest any pull request) Moreover I am not a Jourgen Holler who is an author of 80% of spring core source as far as I know.
-
Vasyl Sarzhynskyi almost 4 yearswant to add that with newer versions of
Spring
, annotationConditionalOnProperty
should be updated@ConditionalOnProperty(name = "test.configname", havingValue = "value1")