Spring @ConditionalOnProperty Example

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.

Source Code

Download

1 thought on “Spring @ConditionalOnProperty Example

  1. 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?

Leave a Reply

Your email address will not be published. Required fields are marked *