Spring Boot – CommandLineRunner
What is use of Spring Boot CommandLineRunner Interaface?
CommandLineRunner Interface is used to execute specific lines of code/task just before the Spring Boot Application starts-up.
How CommandLineRunner works?
We need to create spring bean using CommandLineRunner
interface and spring boot will automatically detect them. CommandLineRunner
Interface have run()
method that needs to be overridden in implementing class and make the class as bean by using spring stereotype such as @Component
.
The arguments which we pass to main()
method while starting spring boot, can be accessed in the run()
method of CommandLineRunner.
run()
method accepts array of String
as an argument.
We can create more than one bean of CommandLineRunner
implementing classes. To execute them in an order, we use spring @Order
annotation or Ordered
interface.
CommandLineRunner
andApplicationRunner
serve the same purpose – If you need access toApplicationArguments
instead of the raw String array consider usingApplicationRunner
.
Steps for implementing CommandLineRunner
- Create a class
CommandLineRunnerBean
- Implement
CommandLineRunner
interface forCommandLineRunnerBean
class - Override its
run()
method - When the
SpringApplication.run()
starts the spring boot application then just before finishing startup,CommandLineRunner.run()
will be executed. Therun()
method ofCommandLineRunner
accepts the arguments that are passed while starting server.
CommandLineRunnerBean.java
@Component public class CommandLineRunnerBean implements CommandLineRunner{ private static Logger LOG = LoggerFactory.getLogger(CommandLineRunnerBean.class); @Override public void run(String... args) throws Exception { LOG.info("EXECUTING : command line runner"); for (int i = 0; i < args.length; ++i) { LOG.info("args[{}]: {}", i, args[i]); } } }
Main class of Spring Boot Application
SpringConsoleApplication.java
@SpringBootApplication public class SpringConsoleApplication{ private static Logger LOG = LoggerFactory.getLogger(SpringConsoleApplication.class); public static void main(String[] args) { LOG.info("STARTING THE APPLICATION"); SpringApplication.run(SpringConsoleApplication.class, args); LOG.info("APPLICATION FINISHED"); } }
POM.xml
<?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.6.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.talksinfo</groupId> <artifactId>SpringConsoleApplication</artifactId> <version>0.0.1-SNAPSHOT</version> <name>SpringConsoleApplication</name> <description>Demo project for Spring Console Application</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
Application.properties
spring.main.web-application-type=NONE
Now execute the JAR file of application as below
java -jar SpringConsoleApplication0.0.1-SNAPSHOT.jar HELLO WORLD FROM TALKSINFO
RESULT
2019-08-11 19:39:27.094 INFO 41828 --- [ restartedMain] com.talksinfo.SpringConsoleApplication : Started SpringConsoleApplication in 0.572 seconds (JVM running for 1.206) 2019-08-11 19:39:27.094 INFO 41828 --- [ restartedMain] com.talksinfo.CommandLineRunnerBean : EXECUTING : command line runner 2019-08-11 19:39:27.095 INFO 41828 --- [ restartedMain] com.talksinfo.CommandLineRunnerBean : args[0]: Hello 2019-08-11 19:39:27.095 INFO 41828 --- [ restartedMain] com.talksinfo.CommandLineRunnerBean : args[1]: World 2019-08-11 19:39:27.095 INFO 41828 --- [ restartedMain] com.talksinfo.CommandLineRunnerBean : args[2]: from 2019-08-11 19:39:27.095 INFO 41828 --- [ restartedMain] com.talksinfo.CommandLineRunnerBean : args[3]: TalksInfo 2019-08-11 19:39:27.096 INFO 41828 --- [ restartedMain] com.talksinfo.SpringConsoleApplication : APPLICATION FINISHED
Notice that the run method is called after application context is loaded but before the execution of the main method is complete.
Most console applications will only have a single class that implements CommandLineRunner. If your application has multiple classes that implement CommandLineRunner, the order of execution can be specified using spring @Order
annotation or Ordered
interface.
Example using @Order
annotation:
- Create a class
CommandLineRunnerOne
andCommandLineRunnerTwo
– Project remains same except 2 classes compared with above example - Implement
CommandLineRunner
interface forCommandLineRunnerOne
andCommandLineRunnerTwo
class - Override its
run()
method - When the
SpringApplication.run()
starts the spring boot application then just before finishing startup,CommandLineRunnerOne.run()
andCommandLineRunnerTwo.run()
will be executed one after one. Therun()
method ofCommandLineRunner
accepts the arguments that are passed while starting server. - Attached
CommandLineRunnerOne
andCommandLineRunnerTwo
class
CommandLineRunnerOne.java
@Component @Order(1) public class CommandLineRunnerOne implements CommandLineRunner{ private static Logger LOG = LoggerFactory.getLogger(CommandLineRunnerTwo.class); @Override public void run(String... args) throws Exception { LOG.info("EXECUTING : command line runner 1"); for (int i = 0; i < args.length; ++i) { LOG.info("args[{}]: {}", i, args[i]); } } }
CommandLineRunnerTwo.java
@Component @Order(2) public class CommandLineRunnerTwo implements CommandLineRunner{ private static Logger LOG = LoggerFactory.getLogger(CommandLineRunnerTwo.class); @Override public void run(String... args) throws Exception { LOG.info("EXECUTING : command line runner 2"); for (int i = 0; i < args.length; ++i) { LOG.info("args[{}]: {}", i, args[i]); } } }
Console
2019-08-11 20:34:58.169 INFO 72916 --- [ restartedMain] com.talksinfo.SpringConsoleApplication : Started SpringConsoleApplication in 0.572 seconds (JVM running for 1.206) 2019-08-11 20:34:58.170 INFO 72916 --- [ restartedMain] com.talksinfo.CommandLineRunnerTwo : EXECUTING : command line runner 1 2019-08-11 20:34:58.170 INFO 72916 --- [ restartedMain] com.talksinfo.CommandLineRunnerTwo : args[0]: Hello 2019-08-11 20:34:58.171 INFO 72916 --- [ restartedMain] com.talksinfo.CommandLineRunnerTwo : args[1]: World 2019-08-11 20:34:58.171 INFO 72916 --- [ restartedMain] com.talksinfo.CommandLineRunnerTwo : args[2]: from 2019-08-11 20:34:58.171 INFO 72916 --- [ restartedMain] com.talksinfo.CommandLineRunnerTwo : args[3]: TalksInfo 2019-08-11 20:34:58.171 INFO 72916 --- [ restartedMain] com.talksinfo.CommandLineRunnerTwo : EXECUTING : command line runner 2 2019-08-11 20:34:58.171 INFO 72916 --- [ restartedMain] com.talksinfo.CommandLineRunnerTwo : args[0]: Hello 2019-08-11 20:34:58.171 INFO 72916 --- [ restartedMain] com.talksinfo.CommandLineRunnerTwo : args[1]: World 2019-08-11 20:34:58.171 INFO 72916 --- [ restartedMain] com.talksinfo.CommandLineRunnerTwo : args[2]: from 2019-08-11 20:34:58.171 INFO 72916 --- [ restartedMain] com.talksinfo.CommandLineRunnerTwo : args[3]: TalksInfo 2019-08-11 20:34:58.172 INFO 72916 --- [ restartedMain] com.talksinfo.SpringConsoleApplication : APPLICATION FINISHED