StackTips

How to Execute Code on Spring Boot Application Startup?

Spring boot offers multiple options, for executing your code during the application startup. This post covers some of the ‘out of the box’ practices recommended by the Spring developers.

The @SpringBootApplication

The SpringApplication class provides a convenient way to bootstrap a Spring application that is started from a main() method. This is what a typical Spring boot application looks like:

@Slf4j
@SpringBootApplication
public class KitchenSinkApplication {

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

When your application starts, you should see something similar to the following output:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.6.6)

2022-04-15 09:09:18.318  INFO 69832 --- [           main] c.e.k.demo.KitchenSinkApplication        : Starting KitchenSinkApplication using Java 11.0.11 on neel.local with PID 69832 (/Users/Neel/spring-boot-examples/run-on-startup/build/classes/java/main started by p7111831 in /Users/Neel/spring-boot-examples/run-on-startup)
2022-04-15 09:09:18.321  INFO 69832 --- [           main] c.e.k.demo.KitchenSinkApplication        : No active profile set, falling back to 1 default profile: "default"
2022-04-15 09:09:18.984  INFO 69832 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2022-04-15 09:09:18.991  INFO 69832 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2022-04-15 09:09:18.991  INFO 69832 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.60]
2022-04-15 09:09:19.060  INFO 69832 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2022-04-15 09:09:19.060  INFO 69832 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 700 ms
2022-04-15 09:09:19.333  INFO 69832 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2022-04-15 09:09:19.342  INFO 69832 --- [           main] c.e.k.demo.KitchenSinkApplication        : Started KitchenSinkApplication in 1.27 seconds (JVM running for 2.083)

Option-1: @PostConstruct Annotation

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

@PostConstruct is mainly used to complete the initialization of your application. It is part of the Spring Boot Lifecycle.

If you want to execute some long-running tasks, you should avoid this approach.

@Slf4j
@SpringBootApplication
public class KitchenSinkApplication {

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

    @PostConstruct
    public void init() {
        log.info("Executes after beans are instantiated");
    }
}

Option-2: ApplicationRunner interface

ApplicationRunner or CommandLineRunner 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.

@Slf4j
@Component
public class MyApplicationRunner1 implements ApplicationRunner {

    @Override
    public void run(ApplicationArguments args) {
        log.info("Executed runner1");
    }
}

You could have multiple ApplicationRunner implementations in your code. But where there are multiple runners, spring doesn’t know which order they should execute.

To sort the runners you can use @Order(1) annotation.

For eg, my MyApplicationRunner2 looks something like this.

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Slf4j
@Component
@Order(2)
public class MyApplicationRunner2 implements ApplicationRunner {

    @Override
    public void run(ApplicationArguments args) {
        log.info("Executed runner1");
    }
}

Option-3: ApplicationReadyEvent

Spring boot publishes an event (ApplicationReadyEvent) to indicate that the application is ready to service requests. At this point, all the initialization steps have been completed by then.

@Slf4j
@Component
public class ApplicationStartEvent {

    @EventListener(ApplicationReadyEvent.class)
    public void onReadyEvent() {

        log.info("Executes when the application is ready");
    }
}

Now if we run all three approaches together, this is what the output looks like.

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.6.6)

2022-04-15 09:30:34.578  INFO 81196 --- [ main] c.e.k.demo.KitchenSinkApplication        : Starting KitchenSinkApplication using Java 11.0.11 on neel.local with PID 81196 (/Users/Neel/spring-boot-examples/run-on-startup/build/classes/java/main started by p7111831 in /Users/Neel/spring-boot-examples/run-on-startup)
2022-04-15 09:30:34.582  INFO 81196 --- [ main] c.e.k.demo.KitchenSinkApplication        : No active profile set, falling back to 1 default profile: "default"
2022-04-15 09:30:35.238  INFO 81196 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2022-04-15 09:30:35.246  INFO 81196 --- [ main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2022-04-15 09:30:35.246  INFO 81196 --- [ main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.60]
2022-04-15 09:30:35.312  INFO 81196 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2022-04-15 09:30:35.313  INFO 81196 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 687 ms
2022-04-15 09:30:35.347  INFO 81196 --- [ main] c.e.k.demo.KitchenSinkApplication        : Executes after beans are instantiated
2022-04-15 09:30:35.632  INFO 81196 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2022-04-15 09:30:35.632  INFO 81196 --- [ main] c.e.k.demo.KitchenSinkApplication : Started KitchenSinkApplication in 1.974 seconds (JVM running for 2.86)
2022-04-15 09:30:35.632  INFO 81196 --- [ main] c.e.k.demo.MyApplicationRunner1 : Executed runner1
2022-04-15 09:30:35.632  INFO 81196 --- [ main] c.e.k.demo.MyApplicationRunner2 : Executed runner2
2022-04-15 09:30:35.632  INFO 81196 --- [ main] c.e.k.demo.ApplicationStartEvent : Executes when application is ready

Download Project on Github

Check out the complete source code for this example here on Github.

nilanchala avtar

Nilanchala Panigrahy

A blogger, a bit of tech freak and a software developer. He is a thought leader in the fusion of design and mobile technologies. He is the author of Xamarin Mobile Application Development for Android Book (goo.gl/qUZ0XV3)