Building custom spring boot auto configurations

What is this about?

This article is about building custom auto configurations for your spring boot application. This requires the knowledge of spring framework and spring boot. In spring boot terms:

Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can "just run".

We take an opinionated view of the Spring platform and third-party libraries so you can get started with minimum fuss. Most spring boot applications need very little Spring configuration.

So what it does is register the beans to the application context automatically if certain conditions are passed, for example, presence of certain classes, libraries, properties, etc. This is to be done manually either through annotations or XML if we are using only the spring framework without spring boot.

For example, if we are having org.springframework.boot:spring-boot-starter-data-jpa library on the classpath, spring boot will try to auto-configure the hibernate session factory, entity manager, data sources, connection pools, etc if the data source properties are provided in the application.[properties | yml]. So here the condition is data source properties and the library presence to auto-configure the data source.

To learn more about spring boot: Spring Boot

How do we implement this?

There are three main steps in this process that spring boot implements internally:

What to do for the configuration?

First is creating the normal configuration class annotated with @Configuration and instantiate the necessary beans using the @Bean annotated methods. An example is below:

package dev.sysout.boot;
...

@Configuration
public class SampleAutoConfiguration(){

    @Bean
    public SampleBean sample(){
        new SampleBean();
    }
}

If we need to create this bean only if certain conditions are passed, then we can add the annotations @ConditionalOnClass, @ConditionalOnProperty, etc at the class or method level. See the list of all conditions available here.

package dev.sysout.boot
...
...
    @Bean
    @ConditionalOnProperty(name="autoconfigure.sample.enabled", havingValue="true")
    // Bean is only registered only when `autoconfigure.sample.enabled` is `true`
    public SampleBean sample(){
        new SampleBean();
    }
    ...

How to tell spring boot about this?

Create a file name spring.factories in the src/main/resources/META-INF folder of your project where the configuration class is present. The content of this file is as below:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=dev.sysout.boot.SampleAutoConfiguration, \
...
# Any other auto configuration classes

Spring boot will also consider this during the application startup.

How to use this?

Now it is just the matter of including this library in the required application classpath, just like we do for the spring boot starter.

    <dependency>
        <groupId>dev.sysout.boot</groupId>
        <artifactId>sample-autoconfigure</artifactId>
        <version>1.0.0</version>
    </dependency>

If all the conditions are satisfied, spring boot will auto-configure the beans in the application context. The debug analysis of the spring boot auto configuration we generally get, we will also get for the custom auto configurations.

...
   SampleAutoConfiguration matched:
      - @ConditionalOnProperty (autoconfigure.sample.enabled=true) matched (OnPropertyCondition)
...

What is the use of this?

If you are having only one application, then there is no specific reason to build the autoconfiguration. But if you are having an application with modular architectures, like microservices, you may need some kind of auto configuration available in every service. For example, spring data jpa auditing feature. In this case, this helps in reducing one additional task to care about in all the services.

In this post, I have written a simple example of a spring boot autoconfiguration. You can add various conditionals, create your own conditionals, validations for properties, failure analyzers (example, the beautiful log we get if we have spring-data-jpa on the classpath but not the data source properties), etc. For more details, refer the links provided below.

How do I know about this?