CommandLineRunner interface
Spring boot provides CommandLineRunner
interface located in org.springframework.boot
package.
CommandLineRunner
allows you to run code after the application context has been fully loaded.
It is an effective way to perform tasks at spring boot application startup such as
- data initialization,
- establishing database connections,
- performing validations etc.
Spring docs state,
Interface used to indicate that a bean should run when it is contained within SpringApplication.
When a class or bean implements CommandLineRunner
interface, it needs to implement its run()
method.
run()
is automatically invoked after Spring ApplicationContext is initialized.
Its signature is
void run(String... args) throws Exception;
Note that the argument of run()
is a string array.
This is the same array that is supplied to the main method of spring boot application.
So, you can get access to application arguments inside a class that implements CommandLineRunner
.
Below is an example of a bean that implements
CommandLineRunner
and implements its run()
method.
import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; @Component public class MyRunner implements CommandLineRunner { @Override public void run(String... args) throws Exception { // add your startup code here System.out.println("Application started!"); } }
You can provide your own custom logic inside run()
that is specific to your application.
Remember that it is up to you how the bean implementing CommandLineRunner
interface is registered, since there are many ways to create a bean in spring.
Error handling
If you look at the signature of run()
, it declares to throw an exception.
So, if an exception arises in run()
and it is not handled, then it will propagate above and prevent the application from starting up.
Thus, it is important that exception should be handled properly inside run()
.
There are following two ways to handle exception in run()
.
1. Using try-catch
This is a standard exception handling mechanism of java, where you enclose the code that might generate an exception between try-catch block.
import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; @Component public class AppInitializer implements CommandLineRunner { @Override public void run(String... args) throws Exception { try { // code } catch (Exception e) { // handle exception System.err.println("Error: " + e.getMessage()); } } }
2. Using ExitCodeGenerator
Spring boot provides an ExitCodeGenerator
interface, which allows you to return an integer value, which is the exit code for in case an error occurs.
It contains getExitCode()
method that returns a non-zero value (such as 1) to indicate an error condition.
import org.springframework.boot.CommandLineRunner; import org.springframework.boot.ExitCodeGenerator; import org.springframework.stereotype.Component; @Component public class AppInitializer implements CommandLineRunner, ExitCodeGenerator { @Override public void run(String... args) throws Exception { // code } @Override public int getExitCode() { // return non-zero exit code to indicate an error return 1; } }
Spring boot automatically detects the presence of an exit code generator.
When an exception occurs in CommandLineRunner
bean’s run()
method, it calls getExitCode()
method to determine the application’s exit code.
It might be possible that multiple classes implement
CommandLineRunner
interface in the same application.Also, they might need to be executed in a specific order.
This can be done using @Order
annotation over the class implementing CommandLineRunner.
@Order is followed by a numeric value between parenthesis.
The bean having a lower order value is executed before the bean having a higher order value.
import org.springframework.boot.CommandLineRunner; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; @Component @Order(1) public class ConnectionInitializer implements CommandLineRunner { @Override public void run(String... args) throws Exception { // code System.out.println("Connections initialized."); } }
import org.springframework.boot.CommandLineRunner; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; @Component @Order(2) public class DataInitializer implements CommandLineRunner { @Override public void run(String... args) throws Exception { // code System.out.println("Data initialized."); } }
In above example, run()
method of ConnectionInitializer
is executed before that of DataInitializer
bean.
If no @Order
annotation is provided, then the run()
methods will be executed in the order the beans are found in the application context.
Conclusion
In this article, we learned how to use spring boot CommandLineRunner
interface to execute custom code during application startup.