Introduction
We will create examples on Spring @ConditionalOnProperty
. The @ConditionalOnProperty
annotation allows 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
Eclipse 2019-06 (4.12), Java 12, Gradle 5.6, Spring Boot 2.1.7
Creating Project
Create a gradle based project in Eclipse with the project name as spring-conditional-on-property.
Updating Build Script
The default generated build.gradle script does not include required dependencies, so we will update the build script as follows to include the spring boot dependencies.
buildscript {
ext {
springBootVersion = '2.1.7.RELEASE'
}
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'org.springframework.boot'
sourceCompatibility = 12
targetCompatibility = 12
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web:${springBootVersion}")
}
Creating Service Class
We 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 {
}
Creating Spring Config Class
We will create Spring Config class with the below source code.
We have used here prefix
and name
to denote the configuration property. Therefore the actual property name is module.enabled
.
We 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();
}
}
Creating 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 we will work with 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 we 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"})
.
Source Code
Thanks for reading.
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?