Custom Spring boot starter

When we create any spring boot application then we add some spring boot starter in it according to the requirements of the application.

Starters are nothing, just a set of convenient dependency descriptors that you can include in your application. The starters contain a lot of dependencies that you need to start your project up and running quickely, effectively and you don’t need to worry about all the transitive dependency in a project, it is automatically added by spring boot starters.

We can also write our own custom starters. If we have an internal library for use within our organization, it would be a good practice to also write a starter for it if it’s going to be used in Spring Boot context.

In today’s post we are going to explain, how we can create our own spring boot starter.

Creating a custom starter

To create a custom starter we need to do the followign things:

  • An auto configuration class along with the custom properties which will be responsible for loading all the beans for custom application on the basis of some conditions.
  • A condition class, which will result whether we’ll have to auto configure all the beans of our custom project or not.
  • A starter pom file which will be including in client application in order to access functionality of custom starter.
  • Add autoconfiguration class in spring.factories file

Creating a autoconfiguration class

Before create an auto configuration class, let’s create a class of custom properties that we want to specify in application.properties file for our custom starter as below:

@Getter
@Setter
@ConfigurationProperties(prefix = "threadminions.connector.http")
public class HttpConnectorProperties {
   private boolean isConnectorEnabled;
}

In above code snippet, we created a class having property isConnectorEnabled and every property should be define in application.properties file with prefix threadminions.connector.http for our custom starter.

Let’s define our condition class, on which basis our custom starter will be initialized and will configure all the required beans in order to access custom functionality as below:

public class HttpCondition extends SpringBootCondition {

    public HttpCondition() {}

    @Override
    public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
        HttpConnectorProperties httpConnectorProperties = getHttpConnectorProperties(context);

        if(!httpConnectorProperties.isConnectorEnabled())
            return ConditionOutcome.noMatch("Http Connector is disabled, because threadminions.connector.enabled is false" );

        return ConditionOutcome.match();
    }

    private HttpConnectorProperties getHttpConnectorProperties(ConditionContext context) {
        HttpConnectorProperties connectorProperties = new HttpConnectorProperties(context.getEnvironment());
        Binder.get(context.getEnvironment()).bind("threadminions.connector.http", Bindable.ofInstance(connectorProperties));
        return connectorProperties;
    }
}

In above code snippet, In order to create a condition class, we need to extends the class with SpringCondition and need to override method name getMatchOutcome which will just check if property is specified in application.properties and having value true the return match() else return noMatch().

After these classes, let’s create an auto configuration class as below:

@Configuration
@Conditional({HttpCondition.class})
@EnableConfigurationProperties(HttpConnectorProperties.class)
public class HttpConnectorAutoConfiguration {

    @Bean
    public HttpConnector httpConnector()
    {
        return new HttpConnector();
    }
}

HttpConnector class is as below:

public class HttpConnector
{
    public Object get(String url, HttpHeaders httpHeaders)
    {
        return "Get request executed successfully";
    }
}

Setting pom.xml file

A final step towards to making custom starter is setting pom.xml file.

As per the naming convention, all the starters which are not managed by the core Spring Boot team should start with the library name followed by the suffix -spring-boot-starter. So we will call our starter as utility-spring-boot-starter:

<?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 http://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>2.1.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>threadminions</groupId>
    <artifactId>utility-spring-boot-starter</artifactId>
    <version>1.0</version>
    <name>utility-starter</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>
    </dependencies>
</project>

In this, add spring-boot-autoconfigure in order to create it as autoconfigure module by spring.

Add autoconfigure class in spring.factories

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
threadminions.utility.connector.HttpConnectorAutoConfiguration

Just create a folder with name META-INF inside the resources folder and create a file inside it with name spring.factories and add following properties in it:

Define all the auto configuration classes with comma separated in this file. In this case, we have only one class so just added as above.

This was all about how to define your custom spring boot starter. It’s time to build it and use it in a different project.

Just build it with mvn clean install package and let’s create an another project and add dependency in it’s pom file as below:

<dependency>
			<groupId>threadminions</groupId>
			<artifactId>utility-spring-boot-starter</artifactId>
			<version>1.0</version>
		</dependency>

After adding dependency, just define the property in application.properties file as below:

threadminions.connector.http.enabled=true

And add following code snippet in order to access the HttpConnector:

 @Autowired
    HttpConnector httpConnector;

    @Override
    public void run(String... args) throws Exception {
        System.out.println(httpConnector.get("htp://abc.com", null));
    }

When you will execute your application, you will get following output:

2019-08-07 16:05:28.483 INFO 2061 — [ main] t.sampleapp.SampleAppApplication : Starting SampleAppApplication on decimal-ThinkPad-E460 with PID 2061 (/home/decimal/threadminions/sample-app/target/classes started by decimal in /home/decimal/threadminions/sample-app)
2019-08-07 16:05:28.487 INFO 2061 — [ main] t.sampleapp.SampleAppApplication : No active profile set, falling back to default profiles: default
2019-08-07 16:05:29.844 INFO 2061 — [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 9001 (http)
2019-08-07 16:05:29.879 INFO 2061 — [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2019-08-07 16:05:29.880 INFO 2061 — [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.22]
2019-08-07 16:05:29.957 INFO 2061 — [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2019-08-07 16:05:29.957 INFO 2061 — [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1417 ms
2019-08-07 16:05:31.242 INFO 2061 — [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService ‘applicationTaskExecutor’
2019-08-07 16:05:32.881 INFO 2061 — [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 9001 (http) with context path ”
2019-08-07 16:05:32.888 INFO 2061 — [ main] t.sampleapp.SampleAppApplication : Started SampleAppApplication in 4.793 seconds (JVM running for 5.38)
Get request executed successfully

As you can see above, your starter method has been executed successfully.

To know more about it click here

That’s all about creating a custom spring boot starter.

Demo code can be found here

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s