Spring Boot @ConditionalOnProperty Annotation Example

In this section we will learn about @ConditionalOnProperty Annotation.


The @ConditionalOnProperty annotation allows us to enable configuration based on the Spring Environment property. Use the prefix and name attributes to specify the property to validate. By default, any property that exists and is not false is mapped. We can also create more complex checks using the havingValue and matchIfMissing attributes.

It may be useful in many cases for example enable/disable service if specific property is available.

The @ConditionalOnProperty annotation may be used on any class annotated with @Configuration@Component@Service & @Repository or on methods annotated with @Bean.

1. Using @ConditionalOnProperty on @Bean method

To illustrate the use of @ConditionalOnProperty, we will develop a basic notification system. To keep things simple for now, let's assume we want to send email notifications.

Suppose we have a key = notification.service and value = twitter in the application.properties file.

notification.service=twitter

Next we'll need to create a simple service to send a notification. For example, consider the Notification Sender interface:

public interface NotificationService {

String sendNotification(String message);
}

Next, let's introduce the implementation of the Notification Sender interface for sending our emails:

public class EmailNotificationService implements NotificationService {

@Override
public String sendNotification(String message) {
return "Email Notification: " + message;
}
}


Now let's see how to use the @ConditionalOnProperty annotation. Let's configure the Notification Sender bean so that it is loaded only if the notification.service property is defined:

@ConditionalOnProperty
(prefix = "notification",
name = "service")
@Bean(name = "emailNotification")
public NotificationService emailNotificationService()
{
return new EmailNotificationService();
}

As we can see, the prefix and name attributes are used to indicate the configuration property to be checked.


Suppose we want to add another notification service – for example, a service that will allow us to send Twitter notifications.

To do this, we need to create another Notification Sender implementation:

public class TwitterNotificationService implements NotificationService{
@Override
public String sendNotification(String message) {
return "Twitter Notification: " + message;
}
}


Since we have two implementations, let's see how we can use @ConditionalOnProperty to load the correct NotificationSender bean conditionally. 


For this purpose, the annotation specifies an attribute that has the value. Interestingly enough, it defines the value that a property must have to add a particular component to the Spring IOC container.


Now let's clarify under what conditions we want to register the Twitter notification implementation in the context:

@ConditionalOnProperty
(prefix = "notification",
name = "service",
havingValue = "twitter")
@Bean(name = "twitterNotification")
public NotificationService twitterNotificationService()
{
return new TwitterNotificationService();
}

With the having Value attribute, we made it clear that we want to load the Twitter notification only when the notification.service is set to twitter.


2. Using @ConditionalOnProperty on @Service class

Suppose we want to add another notification service – for example, a service that will allow us to send SMS notifications.

To do this, we need to create another Notification Sender implementation:

@Service("smsNotification")
@ConditionalOnProperty
(prefix = "notification",
name = "service")
public class SMSNotificationService implements NotificationService{
@Override
public String sendNotification(String message) {
return "SMS Notification: " + message;
}
}

As we can see, the prefix and name attributes are used to indicate the configuration property to be checked. 

@ConditionalOnProperty has another attribute called matchIfMissing. If true it will match the condition and execute the annotated code when property itself is not available in environment.

The following example creates a Spring Boot web application which uses @ConditionalOnProperty annotation.

Project Directory



pom.xml

<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.knf.dev.demo</groupId>
<artifactId>spring-conditionalonproperty-annotation-example</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-conditionalonproperty-annotation-example</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>


application.properties

notification.service=twitter


NotificationService.java

package com.knf.dev.demo.service;

public interface NotificationService {

String sendNotification(String message);
}


EmailNotificationService.java

package com.knf.dev.demo.service;

public class EmailNotificationService implements NotificationService {

@Override
public String sendNotification(String message) {
return "Email Notification: " + message;
}
}


TwitterNotificationService.java

package com.knf.dev.demo.service;

public class TwitterNotificationService implements NotificationService{
@Override
public String sendNotification(String message) {
return "Twitter Notification: " + message;
}
}


AppConfig.java

package com.knf.dev.demo.config;

import com.knf.dev.demo.service.EmailNotificationService;
import com.knf.dev.demo.service.NotificationService;
import com.knf.dev.demo.service.TwitterNotificationService;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {

@ConditionalOnProperty
(prefix = "notification",
name = "service")
@Bean(name = "emailNotification")
public NotificationService emailNotificationService()
{
return new EmailNotificationService();
}

@ConditionalOnProperty
(prefix = "notification",
name = "service",
havingValue = "twitter")
@Bean(name = "twitterNotification")
public NotificationService twitterNotificationService()
{
return new TwitterNotificationService();
}

}


SMSNotificationService.java

package com.knf.dev.demo.service;

import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;

@Service("smsNotification")
@ConditionalOnProperty
(prefix = "notification",
name = "service")
public class SMSNotificationService implements NotificationService{
@Override
public String sendNotification(String message) {
return "SMS Notification: " + message;
}
}


Run the application - Application.java

package com.knf.dev.demo;

import com.knf.dev.demo.service.EmailNotificationService;
import com.knf.dev.demo.service.NotificationService;
import com.knf.dev.demo.service.SMSNotificationService;
import com.knf.dev.demo.service.TwitterNotificationService;
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 Application implements CommandLineRunner {

@Autowired
NotificationService emailNotification;

@Autowired
NotificationService twitterNotification;

@Autowired
NotificationService smsNotification;

public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}

@Override
public void run(String... args) throws Exception {

System.out.println(emailNotification.
sendNotification("Email message"));
System.out.println(twitterNotification.
sendNotification("Twitter message"));
System.out.println(smsNotification.
sendNotification("SMS message"));
}
}

Application is the entry point that sets up the Spring Boot application. The @SpringBootApplication annotation enables auto-configuration and component scanning. 

Let's run this Spring boot application from either IntelliJ IDEA IDE by right click - Run 'Application.main()'
Or you can use the below maven command to run:

mvn spring-boot:run

Console Output:
Email Notification: Email message
Twitter Notification: Twitter message
SMS Notification: SMS message


Download Source Code

More related topics,

Spring Web Annotations


Spring Core Annotations

Popular posts from this blog

Learn Java 8 streams with an example - print odd/even numbers from Array and List

Java Stream API - How to convert List of objects to another List of objects using Java streams?

Registration and Login with Spring Boot + Spring Security + Thymeleaf

Java, Spring Boot Mini Project - Library Management System - Download

ReactJS, Spring Boot JWT Authentication Example

Top 5 Java ORM tools - 2024

Java - Blowfish Encryption and decryption Example

Spring boot video streaming example-HTML5

Google Cloud Storage + Spring Boot - File Upload, Download, and Delete