1. Overview

In this short tutorial, we’ll examine the main purpose of the @ConditionalOnProperty annotation.

First, we’ll start with a bit of background about what @ConditionalOnProperty is. Then we’ll look at some practical examples to help understand how it works and what features it brings.

2. The Purpose of @ConditionalOnProperty

Typically, when developing Spring-based applications, we need to create some beans conditionally based on the presence and value of a configuration property.

For example, we may want to register a DataSource bean to point to a production or test database depending on if we set a property value to “prod” or “test.”

Fortunately, achieving this isn’t as hard as it might look upon first glance. The Spring framework provides the @ConditionalOnProperty annotation precisely for this purpose.

In short, the @ConditionalOnProperty enables bean registration only if an environment property is present and has a specific value. By default, the specified property must be defined and not equal to false.

Now that we’re familiar with the purpose of the @ConditionalOnProperty annotation, let’s dig deeper to see how it works.

3. The @ConditionalOnProperty Annotation in Practice

To exemplify the use of @ConditionalOnProperty, we’ll develop a basic notification system. To keep things simple for now, let’s assume that we want to send email notifications.

First, we’ll need to create a simple service to send a notification message. For instance, consider the NotificationSender interface:

public interface NotificationSender {
    String send(String message);
}

Next, let’s provide an implementation of the NotificationSender interface to send our emails:

public class EmailNotification implements NotificationSender {
    @Override
    public String send(String message) {
        return "Email Notification: " + message;
    }
}

Now let’s see how to make use of the @ConditionalOnProperty annotation. Let’s configure the NotificationSender bean in such a way that it’ll only be loaded if the property notification.service is defined:

@Bean(name = "emailNotification")
@ConditionalOnProperty(prefix = "notification", name = "service")
public NotificationSender notificationSender() {
    return new EmailNotification();
}

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

Finally, we need to add the last piece of the puzzle. Let’s define our custom property in the application.properties file:

notification.service=email

4. Advanced Configuration

As we’ve already learned, the @ConditionalOnProperty annotation allows us to register beans conditionally depending on the presence of a configuration property.

However, we can do more than just that with this annotation*.* So let’s explore!

Let’s suppose we want to add another notification service, such as a service that will allow us to send SMS notifications.

To do that, we need to create another NotificationSender implementation:

public class SmsNotification implements NotificationSender {
    @Override
    public String send(String message) {
        return "SMS Notification: " + message;
    }
}

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

For this purpose, the annotation provides the havingValue attribute. Quite interestingly, it defines the value that a property must have in order for a specific bean to be added to the Spring container.

Now let’s specify under which condition we want to register the SmsNotification implementation in the context:

@Bean(name = "smsNotification")
@ConditionalOnProperty(prefix = "notification", name = "service", havingValue = "sms")
public NotificationSender notificationSender2() {
    return new SmsNotification();
}

With the help of the havingValue attribute, we made it clear that we want to load SmsNotification only when notification.service is set to sms.

It’s worth mentioning that @ConditionalOnProperty has another attribute called matchIfMissing. This attribute specifies whether the condition should match, in case the property isn’t available.

Now let’s put all the pieces together, and write a simple test case to confirm that everything works as expected:

@Test
public void whenValueSetToEmail_thenCreateEmailNotification() {
    this.contextRunner.withPropertyValues("notification.service=email")
        .withUserConfiguration(NotificationConfig.class)
        .run(context -> {
            assertThat(context).hasBean("emailNotification");
            NotificationSender notificationSender = context.getBean(EmailNotification.class);
            assertThat(notificationSender.send("Hello From Baeldung!")).isEqualTo("Email Notification: Hello From Baeldung!");
            assertThat(context).doesNotHaveBean("smsNotification");
        });
}

5. Conclusion

In this brief article, we highlighted the purpose of using the @ConditionalOnProperty annotation*.* Then we learned how to use it to load Spring beans conditionally through a practical example.

As always, the full source code for this article is available over on GitHub.