Spring Boot: How do I execute my code on startup?


You just createad a Spring Boot application using a generator and you want to add some code ... but where?

When you start your new application you will get a simular result in your application

2021-11-24 14:45:35.355  INFO 83348 --- [  restartedMain] ch.genidea.demo.DemoApplication          : Started DemoApplication in 13.166 seconds (JVM running for 13.878) 

Your 'complete' code should look like this one. The main method, as you know, starts a standard Java application. In the case of Spring Boot a SpringApplication is started with your main class as parameter.

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

I recommend to don't modify this code. If you want to run methods during the startup of the application you have multiple options. There are some 'out of the box' practices recommended by the Spring developers.

How can I execute my code on Spring startup?

Here you can find the official documentation: Spring Boot documentation

@PostConstruct (initialization)

You can add @PostConstruct to your main class or to a @Component of your application to execute the code after your application is started.

This solution is thought mainly to complete the initialization of your application and it's part of the Spring Boot Lifecycle.

If you want to run some business tasks and not simply complete the configuration you should look at the next method.

@SpringBootApplication 
public class DemoApplication { 
 
	public static void main(String[] args) { 
		SpringApplication.run(DemoApplication.class, args); 
	} 
} 
 
@PostConstruct 
	public void init(){ 
		System.out.println("init after the beans has been instanciated"); 
	} 
 

CommandLineRunner and ApplicationRunner (run tasks)

Here the official documentation: Using the ApplicationRunner or CommandLineRunner

This is the recommended method if you have to execute some code after the initialization of the application.

You could implement the ApplicationRunner in your main class too, but it's recommended to separate the code in a dedicated class (separation of concerns) that implements one of the two types of Runner.

@SpringBootApplication 
public class DemoApplication implements ApplicationRunner { 
 
	public static void main(String[] args) { 
		SpringApplication.run(DemoApplication.class, args); 
	} 
 
  @Override 
	public void run(ApplicationArguments args) throws Exception { 
		System.out.println("runner is executed");	 
	} 
} 

The ApplicationRunner should be implemented in others @Component inside your project.

You need to implement the run method adding inside the code you want to execute.
The signature of run is : void run(ApplicationArguments args) throws Exception;. The method doesn't return any value, the parameter consists in the arguments used to call the application and can be left off in your task if you don't need it.

@Component 
public class MyStartingCode implements ApplicationRunner { // or CommandLineRunner 
 
    @Override 
    public void run(String... args) { 
       	System.out.println("runner is executed"); 
    } 
 
} 

If you have multiple Runners ... sort them

To sort the runners you can use @Order or implement the Ordered interface.

@Component 
@Order(value = 1) // this gives the sort number to the Runner if other are present. 
public class InitCodeExample implements ApplicationRunner { 
@Component 
@Order(value = 2) // this gives the sort number to the Runner if other are present. 
public class InitCodeSecondExample implements ApplicationRunner { 

In this case InitCodeExample will run before InitCodeSecondExample.

Deep Dive

To understand better the process. SpringApplication.java has a method that search, list, sort and call all the Runners found in the code.

private void callRunners(ApplicationContext context, ApplicationArguments args) { 
		List<Object> runners = new ArrayList<>(); 
		runners.addAll(context.getBeansOfType(ApplicationRunner.class).values()); 
		runners.addAll(context.getBeansOfType(CommandLineRunner.class).values()); 
		AnnotationAwareOrderComparator.sort(runners); 
		for (Object runner : new LinkedHashSet<>(runners)) { 
			if (runner instanceof ApplicationRunner) { 
				callRunner((ApplicationRunner) runner, args); 
			} 
			if (runner instanceof CommandLineRunner) { 
				callRunner((CommandLineRunner) runner, args); 
			} 
		} 
	} 

This method is called after Spring has built the context of the application and started the listeners. As you can notice all the available Runners (ApplicationRunner and CommandLineRunner) are collected in a LinkedHashSet list and sorted regardless of the type.

The execution of your tasks is done during the startup process building the context. When they are completed Spring Boot will return the context and start listening the external events (e.g. in the case of a WebApp).

/** 
	 * Run the Spring application, creating and refreshing a new 
	 * {@link ApplicationContext}. 
	 * @param args the application arguments (usually passed from a Java main method) 
	 * @return a running {@link ApplicationContext} 
	 */ 
	public ConfigurableApplicationContext run(String... args) { 
    ... 
    DefaultBootstrapContext bootstrapContext = createBootstrapContext(); 
		ConfigurableApplicationContext context = null; 
		... 
    SpringApplicationRunListeners listeners = getRunListeners(args); 
		... 
    try { 
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); 
			ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments); 
			... 
      		context = createApplicationContext(); 
			context.setApplicationStartup(this.applicationStartup); 
			... 
			listeners.started(context, timeTakenToStartup); 
			callRunners(context, applicationArguments); // <- LOOK HERE :) 
		} 
		... 
		return context; 
	} 

What is an ApplicationRunner

Spring Doc

It's a functional interface indicating that a bean should run in a SpringApplication.

What is the difference between ApplicationRunner and CommandLineRunner

The CommandLineRunner can receive an array of Strings as parameter. The ApplicationRunner receives an ApplicationArguments as parameter. This provides access to the arguments used to run the SpringApplication



WebApp built by Marco using SpringBoot, Java 16, Mustache, Markdown and Hosted using Jelastic