Tomcat - 9.0.36 Spring Boot Version - 2.3.1.RELEASE
I am trying to convert our Spring web-application from traditional war to Spring-Boot War. In the attached demo project i am creating one Sample Service and ServletContextListener.
When running the built war as Spring Boot executable Order of execution is like Context Initialized Service Created
But when running the same war in Tomcat-9, the execution order is like Service Created Context Initialized
Our application has a need where we need to populate some data in our database at application start up. The listener execution needs to happen first so services cache data when they are getting initialized. Traditional War deployment follows the expected sequence.
Thanks
Comment From: wilkinsona
When you deploy a Spring Boot application as a war file, it is bootstrapped via SpringBootServletInitializer
which you have sub-classed. This is invoked by Spring Framework's SpringServletContainerInitializer
which is a ServletContainerInitializer
. The Servlet spec mandates that all ServletContainerInitializer
s are called before any ServletContextListener
s. In this case that means that the listener is called after your service bean is initialised.
When you execute the war using java -jar
, ServletContainerInitializer
s are not called. Instead, all of the bootstrapping is performed via the application context. This bootstrapping includes calling any ServletContextListener
beans. As noted in the documentation such beans are called very early in the application context's lifecycle. In this case that means they are called before your service bean is initialised.
When there are some ordering requirements, I would avoid mixing Spring bean lifecycle with servlet container lifecycle as it may not give you sufficient control. Rather than using a ServletContextListener
, I would recommend using a Spring bean instead. You can then configure dependencies, for example by using @DependsOn
between this and other beans to control their ordering in which they are called, irrespective of the deployment environment.
Comment From: gurpreetsingh85
ServletContainerInitializer
s are not called
thank you very much @wilkinsona for the detailed explanation. I suggest please add your response in the framework documentation too for both spring and spring-boot. It will definitely help other developers.