Spring Boot – CommandLineRunner

In Spring Boot, a CommandLineRunner is a functional interface with a run() method. Just before Spring boot application finishes its startup, it will automatically call the run() method of all the beans implementing the CommandLineRunner interface.

1. CommandLineRunner Example

Lets start with a very simple usage of CommandLineRunner interface. In given example, we are implementing the CommandLineRunner interface and overriding the run() method to print a simple log statement.

[java title=”Application”]
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application implements CommandLineRunner {

private static final Log logger = LogFactory.getLog(Application.class);

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

@Override
public void run(String… args) throws Exception {
logger.info("Executing run method for Application");
}

}
[/java]

2. When to CommandLineRunner interface?

CommandLineRunner interface is mostly used when we want to execute some functionality immediately after the completion of application startup. The functionalities may include scenarios listed below, but it’s not limited to.

Please note that the run() block executes only once in during startup and never re-run again.

  • Clear or update the stale caches
  • Fetch and prepare the required data before starting to serve the user requests
  • Print the loaded bean names for debugging purpose
  • Trigger the scheduled jobs

The code snippet below demonstrates the execution flow for Appliction implementing CommandLineRunner interface. Here we are printing the application startup arguments.

[java title=”Application.java”]
import java.util.Arrays;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application implements CommandLineRunner {

private final static Log logger = LogFactory.getLog(Application.class);

public static void main(String[] args) {
logger.info("START – Executing main method for Application");
SpringApplication.run(Application.class, args);
logger.info("END – Executing main method for Application");
}

@Override
public void run(String… args) throws Exception {
logger.info("Executing run method for Application");
Arrays.asList(args)
.stream()
.forEach(System.out::println);
}

}
[/java]

3. Multiple CommandLineRunner Beans

We can define multiple CommandLineRunner beans within the same application context. In case of multiple beans, the run() method in all the beans will be executed.

We can be ordere the execution of multiple CommandLineRunner beans using the Ordered interface or @Order annotation.

[java title=”CacheStartup and BatchJobStartup classes”]
@Order(value = 1)
@Component
public class CacheStartup implements CommandLineRunner {

private final static Log logger = LogFactory.getLog(CacheStartup.class);

@Override
public void run(String… args) throws Exception {
logger.info("Executing run method for CacheStartup");
}
}

@Order(value = 2)
@Component
public class BatchJobStartup implements CommandLineRunner {

private final static Log logger = LogFactory.getLog(BatchJobStartup.class);

@Override
public void run(String… args) throws Exception {
logger.info("Executing run method for BatchJobStartup");
}
}
[/java]

When the spring boot application starts, the run() method of CacheStartup will execute before the run() method of BatchJobStartup.

4. CommandLineRunner vs ApplicationRunner

In Spring boot application, both CommandLineRunner and ApplicationRunner serve the same purpose.

They are automatically detected by spring boot and their run() method get executed just before spring boot application finishes its startup. Even the use of @Order annotation is similar in both interfaces.

Only difference between CommandLineRunner vs ApplicationRunner interfaces is how they support the startup arguments.

ApplicationRunner is more advanced than the CommandLineRunner interface.

  • CommandLineRunner.run() method accepts the startup arguments straight into an string array with very little information about how to use them.
  • ApplicationRunner.run() method accepts the startup arguments in ApplicationArguments instance.
    ApplicationRunner provides various method for supporting optional and mandatory startup arguments.
    We can also get the startup arguments as key-value pairs, or get any specific argument by its key name and so on.

[java title=”Application.java”]
@SpringBootApplication
public class Application implements ApplicationRunner {

private final static Log logger = LogFactory.getLog(Application.class);

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

@Override
public void run(ApplicationArguments args) {

final List nonOptionArgs = args.getNonOptionArgs();
final String[] sourceArgs = args.getSourceArgs();
final Set optionNames = args.getOptionNames();

//args.getOptionValues("optionalArgument");
}
}
[/java]

Clearly, ApplicationRunner provides a more fine control over application startup arguments. So ApplicationRunner should be preferred over CommandLineRunner in most cases.

Happy Learning!!

Leave a Comment