Introduction
I will create examples how to work with Spring Conditional on Expression using @ConditionalOnExpression
. The @ConditionalOnExpression
annotation lets configuration be included based on the result of a SpEL (Spring Expression Language) expression. For this example the Module
class is only loaded if a particular SpEL is enabled. This way, you 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
Java at least 1.8, Gradle 5.6 – 6.7.1, Spring Boot 2.1.7 – 2.4.2, Maven 3.6.3
Project Setup
Create a gradle or maven based project in your favorite tool with the project name as spring-conditional-on-expression.
Updating Build Script
The default generated build.gradle script does not include required dependencies, so I will 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}")
}
}
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}")
}
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 {
}
Application Properties File
Create an application.properties file under src/main/resources folder with below content:
module.enabled=true
module.submodule.enabled=true
Spring Config 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();
}
}
Main Class
Create main class to test the 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
.