Spring-boot: Why is my WebApplicationInitializer not loaded

Created on 18 Mar 2014  Â·  15Comments  Â·  Source: spring-projects/spring-boot

I have a really simple Spring-Boot application and I wonder why my WebApplicationInitializer is not recognized by SpringServletContainerInitializer?

At application startup in console everythings looks fine, but there is no System.err-output from the Initializer. Also, if I set a breakpoint inside the onStartup method it is never reached.

Did I miss anything?

Thanks.

My classes:

package de.tbosch.web.springboot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan
@EnableAutoConfiguration
public class Application {

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

}
package de.tbosch.web.springboot;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;

import org.springframework.web.WebApplicationInitializer;

public class Initializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        System.err.println("------------------------------------");
    }

}

Details: https://github.com/dickerpulli/playground/tree/master/web/spring-boot

Most helpful comment

Great hints ...

Now I solved it just with using a ServletContextInitializer instead of WebApplicationInitializer and added this one to my spring context.

@Configuration
public class Initializer implements ServletContextInitializer {

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        System.err.println("------------------------------------");
    }

}

With declaring it as @Configuration I can add it in the main-Method as follows

    public static void main(String[] args) {
        SpringApplication.run(new Class[] { Application.class, Initializer.class }, args);
    }

.... and it's getting loaded.

Thanks a lot!

All 15 comments

I'm not sure what you were expecting, but Spring Boot apps do not execute ServletContainerInitializers so this is not surprising (see #321 for more discussion). I think this is effectively a duplicate of #321 so I'll close it if you don't mind.

What was it you acctually wanted to do? Maybe ServletContextInitializer was what you wanted? Or an ApplicationListener?

I want to register a servlet (CXFServlet) to the servlet context. With deployment in tomcat servlet-3.0 container it works with such a WebApplicationInitializer that registers the servlet in the context.

What do I have to do to make it work with spring boot?

I have a Spring Boot project with a WebApplicationInitializer - the initializer works fine when I build a war and deploy it to a standalone Tomcat 7.
However if I build my Spring Boot app as an executable jar with an embedded Tomcat 7, the WebApplicationInitialier is NOT called when the application is started.

For my project I need to deliver a war file, so it is not a big problem for me, but it would be nice to get this to work the same way regardless of using the embedded Tomcat or deploying to a standalone Tomcat.

I found an old issue on the Tomcat issue tracker that might be related to why my WebApplicationInitializer is not found - apparently the class has to be in a JAR file for the Tomcat scanner to find it.
It should be possible to work around - by doing what Mark suggests in comment #19 - https://issues.apache.org/bugzilla/show_bug.cgi?id=52853#c19.

As for other ways to register servlets/filters in a Spring Boot Web application you should be able to create a @Bean in your configuration that returns a Servlet, or Filter - have a look at http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#howto-add-a-servlet-filter-or-servletcontextlistener

Cheers
Flemming

On 18 Mar 2014, at 20:53, Thomas Bosch [email protected] wrote:

I want to register a servlet (CXFServlet) to the servlet context. With deployment in tomcat servlet-3.0 container it works with such a WebApplicationInitializer that registers the servlet in the context.

What do I have to do to make it work with spring boot?

—
Reply to this email directly or view it on GitHub.

As mentioned in #321 not calling WebApplicationInitializers is an intentional design decision.

You should be able to register a @Bean of type org.springframework.boot.context.embedded.ServletContextInitializer and use that to delegate to your existing WebApplicationInitializer. Or you can register Servlets and Filters (either directly or using the ServletRegistrationBean or FilterRegistrationBean classes).

Great hints ...

Now I solved it just with using a ServletContextInitializer instead of WebApplicationInitializer and added this one to my spring context.

@Configuration
public class Initializer implements ServletContextInitializer {

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        System.err.println("------------------------------------");
    }

}

With declaring it as @Configuration I can add it in the main-Method as follows

    public static void main(String[] args) {
        SpringApplication.run(new Class[] { Application.class, Initializer.class }, args);
    }

.... and it's getting loaded.

Thanks a lot!

And do you know what? It works like a charm! Thanks!

dickerpulli, I don't understand, I do as you do, I get the exception message:

java.lang.IllegalStateException: Cannot initialize context because there is already a root application context present - check whether you have multiple ContextLoader* definitions in your web.xml!
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:277)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4971)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5467)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)

what can I do??

Sorry, but I can't help.
It seems that your have two root application contexts you want to initialize. Do you have published the code so that I can take a look ... ?

Thank you for your response
All I what to do is start the Application in embedded tomcat so I can debug in Eclipse.
I choose the most simple example "http://spring.io/guides/tutorials/rest/3/" which in Spring.IO guides.
Can you tell me how to start the application with sprint-boot ??

That tutorial is not a Spring Boot app (for some unknown reason). Look at the gs guides http://spring.io/guides/gs for loads of simpler examples. Nearly all of those have a main method. You can also find simple examples in the Spring Boot docs and source code.

If this is true, the documentation seems extremely misleading. http://docs.spring.io/autorepo/docs/spring-framework/4.1.x/javadoc-api/org/springframework/web/WebApplicationInitializer.html states that WebApplicationInitializers are detected automatically, speaks of a 100% code based approach etc. Never mentions this caveat. Is there some kind of recipe available here?

@mschipperheyn Sorry that you've found the documentation misleading. Unfortunately, you're looking at the documentation for Spring _Framework_ and this issue is for Spring _Boot_. The latter takes a more opinionated view of the world than the former. One of those opinions is that WebApplicationInitializers are not supported when running your application as an executable jar. They are, however, supported when you deploy a Spring Boot war to a servlet container. I've just looked in the reference guide and it looks like we haven't done a good job of documenting this. I've opened https://github.com/spring-projects/spring-boot/issues/4643 so that we can improve Spring Boot's documentation.

the problem is solved?

@XiHaHa This issue has been closed since 2015. If you have a problem or a question please ask on stackoverflow.com.

I think SpringBootServletInitializer is the equivalent of WebApplicationInitializer in boot projects and it should work in spring-boot

Was this page helpful?
0 / 5 - 0 ratings