Introduction
Here I will create examples on Spring conditional on property using the annotation @ConditionalOnProperty
. The @ConditionalOnProperty
annotation allows you to load beans conditionally depending on a certain environment property or configuration of a property.
Use the prefix
and name
attributes to specify the property that should be checked. By default, any property that exists and is not equal to false
is matched. You can also create more advanced checks by using the havingValue
and matchIfMissing
attributes.
Prerequisites
Java at least 8, Gradle 5.6 – 6.7.1, Maven 3.6.3, Spring Boot 2.1.7 – 2.4.2
Project Setup
Create a gradle or maven based project in your favorite IDE or tool with the project name as spring-conditional-on-property.
The default generated build.gradle script does not include required dependencies, so you need update the build script as follows to include the spring boot dependencies.
buildscript {
ext {
springBootVersion = '2.1.7.RELEASE' to 2.4.2
}
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
plugins {
id 'java-library'
id 'org.springframework.boot' version "${springBootVersion}"
}
sourceCompatibility = 12
targetCompatibility = 12
repositories {
mavenCentral()
jcenter()
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web:${springBootVersion}")
}
For maven based project you can use the following pom.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.roytuts</groupId>
<artifactId>spring-conditional-on-property</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>12</maven.compiler.source>
<maven.compiler.target>12</maven.compiler.target>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.2</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Service Class
I will create simple service class without any methods in it. Ideally this service class will have some methods to perform your project’s business operations.
package com.roytuts.spring.conditional.on.property;
public class SpringService {
}
Spring Config Class
I will create Spring Config class with the below source code.
I have used here prefix
and name
to denote the configuration property. Therefore the actual property name is module.enabled
.
I have matchIfMissing = true
in the @ConditionalOnProperty
and it means that if the property module.enabled
does not exist, it will still be loaded.
The SpringService
is only loaded if the module.enabled
property has the value true
. So in the following scenario the SpringService
will be loaded.
package com.roytuts.spring.conditional.on.property;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SpringConfig {
@Bean
@ConditionalOnProperty(prefix = "module", name = "enabled", matchIfMissing = true)
public SpringService springService() {
return new SpringService();
}
}
Main Class
A class with main method is enough to run the Spring Boot application.
package com.roytuts.spring.conditional.on.property;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringConditionalOnPropertyApp implements CommandLineRunner {
@Autowired
private SpringService springService;
public static void main(String[] args) {
SpringApplication.run(SpringConditionalOnPropertyApp.class, args);
}
@Override
public void run(String... args) throws Exception {
System.out.println("Spring service fully qualified class name: " + springService.getClass());
}
}
Testing the Application
On executing the main class you will get below output:
Spring service fully qualified class name: class com.roytuts.spring.conditional.on.property.SpringService
Other Scenarios
Now I will show you other scenarios.
For example let’s remove the tag matchIfMissing = true
, i.e., @ConditionalOnProperty(prefix = "module", name = "enabled")
and execute the main class. You will get the following error:
The following candidates were found but could not be injected:
- Bean method 'springService' in 'SpringConfig' not loaded because @ConditionalOnProperty (module.enabled) did not find property 'enabled'
Why? Because you removed the matchIfMissing = true
and you did not configure the property in properties file.
So put the property module.enabled=true
into src/main/resources/application.properties file.
Now executing main class will not give any error and SpringService
bean will be loaded.
Let’s say you have configured with havingValue = "true"
as shown below:
@ConditionalOnProperty(prefix = "module", name = "enabled", havingValue = "true")
So if the property has value true then only SpringService
bean will be loaded.
Now if you make havingValue = "false"
then your bean SpringService
will not be loaded and you will see below error:
The following candidates were found but could not be injected:
- Bean method 'springService' in 'SpringConfig' not loaded because @ConditionalOnProperty (module.enabled=false) found different value in property 'enabled'
If you do not configure the property in properties file and havingValue = "true"
with matchIfMissing = true
does not make sense.
You can also use only @ConditionalOnProperty(prefix = "module", value = "enabled")
to load the SpringService
because the value of module.enabled
is true
(module.enabled=true) in the properties file.
But if you configure as module.enabled=false
, then SpringService
bean will not be loaded and you will get below error.
The following candidates were found but could not be injected:
- Bean method 'springService' in 'SpringConfig' not loaded because @ConditionalOnProperty (module.enabled) found different value in property 'enabled'
You can also pass as value
in place of name
. You can also pass multiple names or multiple values but prefix
will be only one.
To pass value instead of name, you can use @ConditionalOnProperty(prefix = "module", value = "enabled")
.
To pass multiple names or values you can use @ConditionalOnProperty(prefix = "module", name = {"enabled", "dynamic"})
.
That’s all about how to work with Spring conditional on property.
Hi ,
If I need to conditionally initialize the below bean with some autowired fields it is giving the error.
package com.roytuts.spring.conditional.on.property;
public class SpringService {
@Autowired
private MongoTemplate template;
}
hey its a good article on @ConditionalonProperty. If i move these property to Git repo and change it dynamically and refresh through actuator, will this annotation work?