Spring Boot SpEL ConditionalOnExpression check multiple properties

As far as i remember, You could use this kind of expression:

@ConditionalOnExpression("'${com.property1}'.equals('${com.property2}')")

for further reading here is the link

if it was helpful, please do comment so that my confusion may also get cleared.


Can be little bit confusing using boolean properties

@Bean
@ConditionalOnExpression("${config.integration.materializedCollectionDeleteEnabled:true}  and  ${config.integration.dbTransactionsEnabled:false}")
public DefaultMaterializedCollectionUpdater defaultMaterializedCollectionUpdater(IntegrationConfig integrationConfig, MongoTemplate mongoTemplate) {
    return new DefaultMaterializedCollectionUpdater(integrationConfig, mongoTemplate);
}

It may seem like bean should be created when I have properties like

config:
  integration:
    dbTransactionsEnabled: false
    materializedCollectionDeleteEnabled: true

But bean does not get created because ${property:value} is giving you default value but not checking if your property has given value. If you want explicitly check property has value then use ==. You still can keep default values though

@Bean
@ConditionalOnExpression("${config.integration.materializedCollectionDeleteEnabled:true} == true  and  ${config.integration.dbTransactionsEnabled:false} == false")
public DefaultMaterializedCollectionUpdater defaultMaterializedCollectionUpdater(IntegrationConfig integrationConfig, MongoTemplate mongoTemplate) {
    return new DefaultMaterializedCollectionUpdater(integrationConfig, mongoTemplate);
}

To debug use org.springframework.expression.spel.standard.Tokenizer constructor


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