Introduction

We will create examples on Spring @ConditionalOnExpression. The @ConditionalOnExpression annotation lets configuration be included based on the result of a SpEL (Spring Expression Language) expression. For our example the Module class is only loaded if a particular SpEL is enabled. This way, we might create similar modules that are only loaded if their respective SpEL has been found or enabled.

SpEL or Spring Expression Language which can be used to query property value from properties file using $, or manipulate Java object and its attributes at runtime using #. Both modifiers $ and # can be used in spring XML configuration file directly, or can be used in Java source code with @Value annotation.

Prerequisites

Eclipse 4.12, Java 1.8, 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-expression.

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 Module Class

Create a simple Module class just to check whether it is loaded or not based on SpEL condition.

package com.roytuts.spring.conditional.on.expression;
public class Module {
}

Creating Properties File

Create an application.properties file under src/main/resources folder with below content.

module.enabled=true
module.submodule.enabled=true

Creating SpringConfig Class

Create below SpringConfig class to load the Module class conditionally.

So if SpEL conditions are evaluated to true, then only Module class will be loaded otherwise not.

package com.roytuts.spring.conditional.on.expression;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConditionalOnExpression(value = "${module.enabled} and ${module.submodule.enabled}")
class SpringConfig {
	@Bean
	public Module module() {
		return new Module();
	}
}

Creating Main Class

Create main class to test our application.

package com.roytuts.spring.conditional.on.expression;
import java.util.Arrays;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
@SpringBootApplication
public class SpringConditionalOnExpressionApp implements CommandLineRunner {
	@Autowired
	private ApplicationContext applicationContext;
	public static void main(String[] args) {
		SpringApplication.run(SpringConditionalOnExpressionApp.class, args);
	}
	@Override
	public void run(String... args) throws Exception {
		String[] beans = applicationContext.getBeanDefinitionNames();
		Arrays.sort(beans);
		boolean contains = Arrays.stream(beans).anyMatch("module"::equalsIgnoreCase);
		if (contains) {
			System.out.println("Module loaded");
		} else {
			System.out.println("Module not loaded");
		}
	}
}

Testing the Application

Now if you run the above main class, you will see below output:

Module loaded

If you make false to any of the keys in the application.properties file then you will get below output:

Module not loaded

You can also check if any of the values is true for the keys in application.properties file in the following way.

@ConditionalOnExpression(value = "${module.enabled} or ${module.submodule.enabled}")

By executing the main class you will get below output:

Module loaded

You can also pass default value to the SpEL using the following way:

@ConditionalOnExpression(value = "${module.enabled:true} and ${module.submodule.enabled:true}")

You can also check for equality of the expression values as shown below:

@ConditionalOnExpression("'${module.enabled}'.equals('${module.submodule.enabled:true}')")

You can use @ConditionalOnExpression on class object’s methods, i.e., @ConditionalOnExpression("#{T(java.lang.Math).random() gt 0}").

Remember the method has to be static.

For the above case, if the random value is greater than 0 then only module will be loaded.

Let’s say you have the following class:

package com.roytuts.spring.conditional.on.expression;
public class SpEL {
	public static String getHello() {
		return "hello";
	}
}

And you want to use method from the above class on @ConditionalOnExpression. Then you can use the following:

@ConditionalOnExpression("#{T(com.roytuts.spring.conditional.on.expression.SpEL).getHello() eq 'hello'}")

or

@ConditionalOnExpression("#{T(com.roytuts.spring.conditional.on.expression.SpEL).getHello()?.equals('hello')}")

For the above case, the module is loaded only when getHello() returns hello.

Source Code

download source code

Thanks for reading.

Tags:

Leave a Reply

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