In this quick tutorial, we’ll explore the two very popular interfaces in Spring Boot: CommandLineRunner and ApplicationRunner.
One common use case of these interfaces is to load some static data at application startup. Though, I have seen such usages mostly for test data setup only.
Both of them are functional interfaces with a run() method. This run() method gets executed soon after the ApplicationContext is loaded and before SpringApplication#run method execution ends.
We have access to the application arguments as a raw String in the CommandLineRunner’s run() method.
Let’s see that with the help of an example.
Firstly, let’s write a bean that implements the CommandLineRunner interface:
@Component public class SampleCmdRunner implements CommandLineRunner { private static final Logger LOG = LoggerFactory.getLogger(SampleCmdRunner.class); @Override public void run(String[] args) { LOG.info("Executing the command line runner, Application arguments: " + Arrays.toString(args)); } }
And now, let’s bootstrap our Spring Boot application executable jar:
java -jar SampleApp-1.0.jar parameter1 parameter2 parameter3
Along with three command-line arguments: parameter1, parameter2, and parameter3.
Our console logs would then be:
s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http) Executing the command line runner, Application arguments: [parameter1, parameter2, parameter3] 2019-09-02 11:02:10.111 INFO 7676 --- [main] com.programmergirl.SampleApp : Started SampleApp in 2.11 seconds
Where all the provided arguments got listed.
Similarly, we can define beans that implement the ApplicationRunner interface:
@Component public class SampleAppRunner implements ApplicationRunner { private static final Logger LOG = LoggerFactory.getLogger(SampleAppRunner.class); @Override public void run(ApplicationArguments args) { LOG.info("Executing SampleAppRunner"); } }
The ApplicationRunner provides access to the ApplicationArguments, not just the raw String arguments. Rather, technically speaking, that’s the only difference between them.
We are free to define any number of CommandLineRunner and ApplicationRunner implementations as we need.
With Java 8 lambda’s, we can have a code:
@SpringBootApplication public class SampleApp { public static void main(String[] args) { SpringApplication.run(SampleApp.class, args); } @Bean CommandLineRunner commandLineRunner() { return args -> System.out.println("CommandLineRunner with args:" + Arrays.toString(args)); } @Bean ApplicationRunner applicationRunner() { return args -> System.out.println("ApplicationRunner with args:" + Arrays.toString(args.getSourceArgs())) } }
Which defines the implementation of these interfaces in our Application class itself.
We can also impose ordering on the execution of these beans using the @Order annotation.
Say, we have two CommandLineRunner implementations:
@Component @Order(1) public class CmdRunner1 implements CommandLineRunner { private static final Logger LOG = LoggerFactory.getLogger(CmdRunner1.class); @Override public void run(String[] args) { LOG.info("In CmdRunner1"); } } @Component @Order(3) public class CmdRunner2 implements CommandLineRunner { private static final Logger LOG = LoggerFactory.getLogger(CmdRunner2.class); @Override public void run(String[] args) { LOG.info("In CmdRunner2"); } }
Along with a class that implements the ApplicationRunner:
@Component @Order(2) public class AppRunner implements ApplicationRunner { private static final Logger LOG = LoggerFactory.getLogger(AppRunner.class); @Override public void run(ApplicationArguments args) { LOG.info("In AppRunner"); } }
Clearly, our CmdRunner1 will get executed first followed by the AppRunner and finally the CmdRunner2.
In this tutorial, we talked about the CommandLineRunner and ApplicationRunner interfaces provided by Spring Boot.