Where do you add initialization code in a Spring Boot application.
Some people think Spring and Spring Boot adds to much “magic” to a Java app, and to some extend I agree.
Have they gone too far in making Java more like a DSL, and have they managed to hide away all imperative code?
I wont go into whether “too far” is the right way to describe it, but it can be quite tricky to understand what is going on under the hood.
One such thing is: I know where my main() method is, but how do I pas arguments, and after starting up Spring Boot, how do I know it has finished
setting up, and done its “startup-whatsamacallit”? When can I assume all beans are setup and ready to use?
I found the following things regarding startup:
- A CmdlineRunner()
- An ApplicationRunner()
- Listening for “startup events”
- There are more but very obscure…
So which one whould I use?
CommandLineRunner
You could provide a Bean of type CommandLineRunner.
The downside is that ALL CommandLineRunners in a project will be called. Not good.
@Bean CommandLineRunner commandLineRunner() { return new CommandLineRunner() { @Override public void run(String... args) throws Exception { log.info("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); log.info("These Lines will get printed on application startup"); log.info("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); } }; }
ApplicationRunner
You could provide a Bean of type ApplicationRunner interface. Similar to CommandLineRunner but you get access to the ApplicationArguments
@Bean ApplicationRunner applicationRunner() { return new ApplicationRunner() { @Override public void run(ApplicationArguments args) throws Exception { log.info("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); log.info("These Lines will get printed on application startup too"); log.info("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); } }; }
ApplicationStartedEvent EventListener
@EventListener public void executeOnStartup(ApplicationStartedEvent event) { log.info("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); log.info("Another way to run something on application startup with event {}", event); log.info("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); }
ContextRefreshedEvent EventListener
To run your code after the context is complete but before the application is started, Then you should use the ContextRefreshedEvent.
@EventListener public void executeOnStartup(ContextRefreshedEvent event) { log.info("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); log.info("Another way to run something on application startup with event {}", event); log.info("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); }
Arguments to SpringApplication.run()
This is the classic way of handling args, old-style
@SpringBootApplication public class Example { public static void main(String[] args) { // Reading Command-Line arguments for(String arg:args) { System.out.println(arg); } SpringApplication.run(Example.class, args); } }
Other ways of passing arguments
There are also a number of ways you could pass arguments to your Spring Boot app:
- mvn spring-boot:run -Dspring-boot.run.arguments=”–firstName=Peter –lastName=Andersson”
- mvn package java -jar target/[FILENAME.JAR HERE] –firstName=Peter –lastName=Andersson
- server.port=8080 // default values in application.properties
- mvn spring-boot:run -Dspring-boot.run.arguments=–server.port=8081 // overwrite port num using CLI