demo.zip

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 ServletContainerInitializers are called before any ServletContextListeners. In this case that means that the listener is called after your service bean is initialised.

When you execute the war using java -jar, ServletContainerInitializers 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

ServletContainerInitializers 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.