Spring

Spring Boot CommandLineRunner and ApplicationRunner

Introduction:

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.

CommandLineRunner:

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.

ApplicationRunner:

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.

How many ApplicationRunner & CommandLineRunner Implementations?

We are free to define any number of CommandLineRunner and ApplicationRunner implementations as we need.

Java 8 Definitions:

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.

Ordering:

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.

Conclusion:

In this tutorial, we talked about the CommandLineRunner and ApplicationRunner interfaces provided by Spring Boot.

Be the First to comment.

Leave a Comment

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