Runners in Spring Boot

Runners in Spring Boot | Runners in Spring Boot are used to execute any logic only once when the application is getting started. They are used for setup/test purposes/batch processing. Usually, they are used in dev and testing environments.

There are two types of Runners in Spring Boot:-

  • CommandLineRunner(I)
  • ApplicationRunner(I)

Spring boot starter class (main class) will find all runner classes and execute/call them.

CommandLineRunner Interface In Spring Boot

It is a marker interface and contains only one abstract method:- run(). It does not contain any other static or default methods.

To demonstrate it create a Spring boot project. We have to define a class that implements the CommandLineRunner interface overriding the run() method and add @Component.

MyRunner class:- Add @Component to the class, and implement the CommandLineRunner marker interface, which will include the run() method. Write the required logic in the run() method.

package com.knowprogram.demo;

import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

@Component
public class MyRunner implements CommandLineRunner {

    @Override
    public void run(String... args) throws Exception {
        System.out.println("MyRunner.run()");
    }

}

Output In Console:-

Example-2:- Instead of creating a separate class, we can also implement CommandLineRuneer in the starter class as follows:-

package com.knowprogram.demo;

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class CommandLineRunnerDemoApplication implements CommandLineRunner {

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

    @Override
    public void run(String... args) throws Exception {
        System.out.println("CommandLineRunnerDemoApplication.run()");
    }

}

Example-3:- Reading Properties file values and displaying them through CommandLineRunner.

In application.properties file:-

know.app.id = 5
know.app.code = knowprogram
know.app.cost = 5000
package com.knowprogram.demo;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

@Component
public class DataRunner implements CommandLineRunner {

    @Value("${know.app.id}")
    private Integer id;
    
    @Value("${know.app.code}")
    private String code;
    
    @Value("${know.app.cost}")
    private Double cost;

    @Override
    public void run(String... args) throws Exception {
        System.out.println(this);
    }

    @Override
    public String toString() {
        return "DataRunner [id=" + id + ", code=" + code + ", cost=" + cost + "]";
    }

}

In console:-

Working with Multiple Runners in Spring Boot

We can even define multiple runners in the application. They are executed in naming order (A-Z naming rule).

Consider these runners:- SecurityRunner, MvcRunner, and JdbcRunner. They are executed in Naming order:-

  1. JdbcRunner
  2. MvcRunner
  3. SecurityRunner

We can provide our own execution order using annotation @Order(“number”). The lowest number of orders executed first. Example:-

  • ARunner – @Order(30)
  • BRunner – @Order(12)
  • CRunner – @Order(55)

Execution order is: BRunner, ARunner, CRunner

Case-1. If we provide -ve numbers even the same concept. The lowest number is the highest priority. Example:-

  • ARunner – @Order(-51)
  • BRunner – @Order(36)
  • CRunner – @Order(0)
  • DRunner – @Order(12)
  • ERunner – @Order(-25)

Execution order is: ARunner, ERunner, CRunner, DRunner, BRunner.

Case-2. In case of multiple runners, if any runner is not assigned with order then executed last in order.

Case-3. If we give @Order but no value or no annotation even, then the value is: 2147483647 i.e. unordered Runners are executed at last (with naming rule applied). Example:-

  1. A – @Order(5)
  2. B – @Order // value: 2147483647
  3. C – @Order(-9)
  4. D – no annotation even // value: 2147483647
  5. E – @Order // value: 2147483647

Execution flow:-

  • First consider @Order with value: C, A
  • Next, Consider @Order without value / No annotation (Naming Order): B,
  • D, E

Case-4. If runners are given the same order, then again naming rule is applied:-

  • Z – @Order(5)
  • M – @Order(5)
  • A – @Order(5)

Execution flow:- A, M, Z

Always Execution order is A-Z or -ve -> zero -> +ve
The reverse is not possible.

Example of Multiple Runners

We need to execute a few sets of runners in order, like
4 Runners – First
3 Runners – Next
6 Runners – Next
2 Runners – Last

In this case, define one CustomOrder interface and use the same for:-

public interface CustomOrder {
    int FIRST = -9999;
    int NEXT = 1111;
    int MID = 5555;
    int LAST = 9999;
}
@Component
@Order(CustomOrder.MID)
public class AdminRunner implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        System.out.println("Admin.run()");
    }
}
@Component
@Order(CustomOrder.MID)
public class AppTestRunner implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        System.out.println("AppTestRunner.run()");
    }
}
@Component
@Order(CustomOrder.FIRST)
public class DataSourceRunner implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        System.out.println("DataReadRunner.run()");
    }
}
@Component
@Order(CustomOrder.FIRST)
public class DBPoolRunner implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        System.out.println("DBPoolRunner.run()");
    }
}
@Component
@Order(CustomOrder.NEXT)
public class JDBCRunner implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        System.out.println("JDBCRunner.run()");
    }
}
@Component
@Order(CustomOrder.LAST)
public class MVCRunner implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        System.out.println("MVCRunner.run()");
    }
}
@Component
@Order(CustomOrder.LAST)
public class SecurityRunner implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        System.out.println("SecurityRunner.run()");
    }
}

Execution Order:-

If you enjoyed this post, share it with your friends. Do you want to share more information about the topic discussed above or do you find anything incorrect? Let us know in the comments. Thank you!

Leave a Comment

Your email address will not be published. Required fields are marked *