Running code after Spring Boot starts

JavaSpringSpring Boot

Java Problem Overview


I want to run code after my spring-boot app starts to monitor a directory for changes.

I have tried running a new thread but the @Autowired services have not been set at that point.

I have been able to find ApplicationPreparedEvent, which fires before the @Autowired annotations are set. Ideally I would like the event to fire once the application is ready to process http requests.

Is there a better event to use, or a better way of running code after the application is live in spring-boot?

Java Solutions


Solution 1 - Java

It is as simple as this:

@EventListener(ApplicationReadyEvent.class)
public void doSomethingAfterStartup() {
    System.out.println("hello world, I have just started up");
}

Tested on version 1.5.1.RELEASE

Solution 2 - Java

Try:

@Configuration
@EnableAutoConfiguration
@ComponentScan
public class Application extends SpringBootServletInitializer {

    @SuppressWarnings("resource")
    public static void main(final String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);

        context.getBean(Table.class).fillWithTestdata(); // <-- here
    }
}

Solution 3 - Java

Have you tried ApplicationReadyEvent?

@Component
public class ApplicationStartup 
implements ApplicationListener<ApplicationReadyEvent> {

  /**
   * This event is executed as late as conceivably possible to indicate that 
   * the application is ready to service requests.
   */
  @Override
  public void onApplicationEvent(final ApplicationReadyEvent event) {

    // here your code ...

    return;
  }
}

Code from: http://blog.netgloo.com/2014/11/13/run-code-at-spring-boot-startup/

This is what the documentation mentions about the startup events:

>... > >Application events are sent in the following order, as your application runs: > > An ApplicationStartedEvent is sent at the start of a run, but before > any processing except the registration of listeners and initializers. > > An ApplicationEnvironmentPreparedEvent is sent when the Environment to be used in the context is known, but before the context > is created. > > An ApplicationPreparedEvent is sent just before the refresh is started, but after bean definitions have been loaded. > > An ApplicationReadyEvent is sent after the refresh and any related callbacks have been processed to indicate the application is ready to > service requests. > > An ApplicationFailedEvent is sent if there is an exception on startup. > >...

Solution 4 - Java

Why not just create a bean that starts your monitor on initialization, something like:

@Component
public class Monitor {
    @Autowired private SomeService service

    @PostConstruct
    public void init(){
        // start your monitoring in here
    }
}

the init method will not be called until any autowiring is done for the bean.

Solution 5 - Java

The "Spring Boot" way is to use a CommandLineRunner. Just add beans of that type and you are good to go. In Spring 4.1 (Boot 1.2) there is also a SmartInitializingBean which gets a callback after everything has initialized. And there is SmartLifecycle (from Spring 3).

Solution 6 - Java

You can extend a class using ApplicationRunner , override the run() method and add the code there.

import org.springframework.boot.ApplicationRunner;

@Component
public class ServerInitializer implements ApplicationRunner {
    
    @Override
    public void run(ApplicationArguments applicationArguments) throws Exception {

        //code goes here

    }
}

Solution 7 - Java

ApplicationReadyEvent is really only useful if the task you want to perform is not a requirement for correct server operation. Starting an async task to monitor something for changes is a good example.

If, however your server is in a 'not ready' state until the task is completed then it's better to implement SmartInitializingSingleton because you'll get the callback before your REST port has been opened and your server is open for business.

Don't be tempted to use @PostConstruct for tasks that should only happen once ever. You'll get a rude surprise when you notice it being called multiple times...

Solution 8 - Java

Use a SmartInitializingSingleton bean in spring > 4.1

@Bean
public SmartInitializingSingleton importProcessor() {
    return () -> {
        doStuff();
    };

}

As alternative a CommandLineRunner bean can be implemented or annotating a bean method with @PostConstruct.

Solution 9 - Java

Best way to execute block of code after Spring Boot application started is using PostConstruct annotation.Or also you can use command line runner for the same.

1. Using PostConstruct annotation

@Configuration
public class InitialDataConfiguration {
	
	@PostConstruct
	public void postConstruct() {
		System.out.println("Started after Spring boot application !");
	}
	
}

2. Using command line runner bean

@Configuration
public class InitialDataConfiguration {

	@Bean
	CommandLineRunner runner() {
		return args -> {
			System.out.println("CommandLineRunner running in the UnsplashApplication class...");
		};
	}
}

Solution 10 - Java

Providing an example for Dave Syer answer, which worked like a charm:

@Component
public class CommandLineAppStartupRunner implements CommandLineRunner {
    private static final Logger logger = LoggerFactory.getLogger(CommandLineAppStartupRunner.class);

    @Override
    public void run(String...args) throws Exception {
        logger.info("Application started with command-line arguments: {} . \n To kill this application, press Ctrl + C.", Arrays.toString(args));
    }
}

Solution 11 - Java

I really like the suggestion for usage of the EventListener annotation by @cahen (https://stackoverflow.com/a/44923402/9122660) since it is very clean. Unfortunately I could not get this to work in a Spring + Kotlin setup. What does work for Kotlin is adding the class as a method parameter:

@EventListener 
fun doSomethingAfterStartup(event: ApplicationReadyEvent) {
    System.out.println("hello world, I have just started up");
}

Solution 12 - Java

Try this one and it will run your code when the application context has fully started.

 @Component
public class OnStartServer implements ApplicationListener<ContextRefreshedEvent> {

	@Override
	public void onApplicationEvent(ContextRefreshedEvent arg0) {
				// EXECUTE YOUR CODE HERE 
	}
}

Solution 13 - Java

You have several choices:

Using CommandLineRunner or ApplicationRunner as a Bean definition:

Spring Boot executes these towards the end of the application startup process. In most circumstances, the CommandLineRunner will do the job. Following is an example of a CommandLineRunner implementation with Java 8:

@Bean
public CommandLineRunner commandLineRunner() {
   return (args) -> System.out.println("Hello World");
}

Note that the args is the String array of arguments. You can also provide an implementation of this interface and define it as a Spring Component:

@Component
public class MyCommandLineRunner implements CommandLineRunner {

    @Override
    public void run(String... args) throws Exception {
        System.out.println("Hello World");
    }
}

You can use the ApplicationRunner if you need better argument management. ApplicationRunner takes an ApplicationArguments instance that has enhanced argument management options.

You can also order the CommandLineRunner and ApplicationRunner beans using Spring's @Order annotation:

 @Bean
 @Order(1)
 public CommandLineRunner commandLineRunner() {
    return (args) -> System.out.println("Hello World, Order 1");
 }

 @Bean
 @Order(2)
 public CommandLineRunner commandLineRunner() {
    return (args) -> System.out.println("Hello World, Order 2");
 }

Using Spring Boot's ContextRefreshedEvent:

Spring Boot publishes several events at startup. These events indicate the completion of a phase in the application startup process. You can listen to the ContextRefreshedEvent and execute custom code:

@EventListener(ContextRefreshedEvent.class)
public void execute() {
    if(alreadyDone) {
      return;
    }
    System.out.println("hello world");
} 

ContextRefreshedEvent is published several times. Thus, ensure to put a check whether the code execution is already finished.

Solution 14 - Java

just implement CommandLineRunner for spring boot application. You need to implement run method,

public classs SpringBootApplication implements CommandLineRunner{

    @Override
    	public void run(String... arg0) throws Exception {
    	// write your logic here 
    		
    	}
}

Solution 15 - Java

you can use @Component

@RequiredArgsConstructor
@Component
@Slf4j
public class BeerLoader implements CommandLineRunner {
    //declare 

    @Override
    public void run(String... args) throws Exception {
        //some code here 

    }

Solution 16 - Java

Best way you use CommandLineRunner or ApplicationRunner The only difference between is run() method CommandLineRunner accepts array of string and ApplicationRunner accepts ApplicationArugument.

Solution 17 - Java

Spring boot provides an ApplicationRunner interface with a run() method to be invoked at application startup. However, instead of raw String arguments passed to the callback method, we have an instance of the ApplicationArguments class.

@Component
    public class AppStartupRunner implements ApplicationRunner {

    @Override
    public void run(ApplicationArguments args) throws Exception {
        //some logic here
    }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionstewstersView Question on Stackoverflow
Solution 1 - JavacahenView Answer on Stackoverflow
Solution 2 - JavaAnton BessonovView Answer on Stackoverflow
Solution 3 - JavaraspacorpView Answer on Stackoverflow
Solution 4 - JavacjstehnoView Answer on Stackoverflow
Solution 5 - JavaDave SyerView Answer on Stackoverflow
Solution 6 - JavaGimhaniView Answer on Stackoverflow
Solution 7 - JavaAndy BrownView Answer on Stackoverflow
Solution 8 - JavaJeffView Answer on Stackoverflow
Solution 9 - JavaNaresh BhadkeView Answer on Stackoverflow
Solution 10 - JavaPaulo PedrosoView Answer on Stackoverflow
Solution 11 - JavaOsteckeView Answer on Stackoverflow
Solution 12 - JavaKaliforniumView Answer on Stackoverflow
Solution 13 - JavaSomnath MusibView Answer on Stackoverflow
Solution 14 - Javaprasad kpView Answer on Stackoverflow
Solution 15 - JavaBRAIEK AYEMNView Answer on Stackoverflow
Solution 16 - JavaRushi VangaView Answer on Stackoverflow
Solution 17 - JavaBilalView Answer on Stackoverflow