2

I have a Spring 3.1 based application hosted under Tomcat 7.x (latest version). The application is configured exclusively with Java (no web.xml, no Spring XML configuration). All unit tests are passing, including ones using the Spring Java configuration (@ContextConfiguration).

The problem is that when the application is deployed, the WebApplicationInitializer implementation is being called multiple times. Repeated registrations of filters and listeners causes exceptions and the application never starts.

I was not expecting WebApplicationInitializer.onStartup() to be called repeatedly and would like to eliminate that behavior if possible. If anyone has suggestions on why this might be happening, and how to stop it, I'd really appreciate it.

Update I believe the problem is external to the initialization class itself, but here it is in case I am mistaken...

public class DeploymentDescriptor implements WebApplicationInitializer {

    private static final Logger LOGGER = LoggerFactory.getLogger("org.ghc.web-app-initializer");

    @Override
    public void onStartup (ServletContext servletContext) throws ServletException {
        // This is the programmatic way of declaring filters. This allows you to order
        // Filters. The order of these security filters DOES MATTER!
        FilterRegistration.Dynamic mockSecurityFilter       = servletContext.addFilter ("mockSecurityFilter", "org.ghc.security.MockSecurityFilter");
        mockSecurityFilter.addMappingForUrlPatterns         (EnumSet.of (REQUEST), true, "/*");

        FilterRegistration.Dynamic siteMinderSecurityFilter = servletContext.addFilter ("siteMinderSecurityFilter", "org.ghc.security.SiteMinderSecurityFilter");
        siteMinderSecurityFilter.addMappingForUrlPatterns   (EnumSet.of (REQUEST), true, "/*");

        FilterRegistration.Dynamic userDetailsStoreFilter   = servletContext.addFilter ("userDetailsStoreFilter", "org.ghc.security.UserDetailsStoreFilter");
        userDetailsStoreFilter.addMappingForUrlPatterns     (EnumSet.of (REQUEST), true, "/*");


        // Static resource handling using "default" servlet
        servletContext.getServletRegistration ("default").addMapping ("*.js", "*.css", "*.jpg", "*.gif", "*.png");
        // Map jspf files to jsp servlet
        servletContext.getServletRegistration ("jsp").addMapping ("*.jspf");


        // Spin up the Spring 3.1 class that can scan a package tree for classes
        // annotated with @Configuration. See org.ghc.spring3.ControllerConfiguration for
        // this example.
        final AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext ();
        dispatcherContext.setServletContext (servletContext);
        dispatcherContext.register(ScProviderDirectory.class);
        dispatcherContext.refresh ();

        // Spin up the Spring DispatcherServlet (just like before) passing the just built
        // application context. Load it like the regular Servlet that it is!
        final ServletRegistration.Dynamic servlet = servletContext.addServlet ("spring", new DispatcherServlet(dispatcherContext));
        servlet.setLoadOnStartup (1);
        servlet.addMapping ("/");  // Make sure this is NOT "/*"!
    }
}

Update 2 This is just weird. The Tomcat logs appear to identify two instances of my DeploymentDescriptor class. I verified that there is only one instance of this class in my .war file though. I have no idea where the second (phantom) instance is coming from, but at least this explains why the class is being scanned twice...

logs/localhost.2012-10-09.log:INFO: Spring WebApplicationInitializers detected on classpath: [org.ghc.configuration.DeploymentDescriptor@3b29642c]
logs/localhost.2012-10-09.log:INFO: Spring WebApplicationInitializers detected on classpath: [org.ghc.configuration.DeploymentDescriptor@432c4c7a]
node42
  • 695
  • 4
  • 10
  • 19
  • Interesting, wondering if some exception is thrown from your intializer, can you add more logs just to be sure – Biju Kunjummen Oct 09 '12 at 21:27
  • I have been watching with a debugger (the real benefit of Java configuration). The first time through everything goes well. The second generates an NPE (servletContext.addFilter() return null, then the call on that filter causes the NPE). Other calls to ServletContext are problematic after the first time as well. – node42 Oct 09 '12 at 21:45
  • I think it is more like two instances of `SpringServletContainerInitializer` which registers the WebApplicationInitializers being detected..may be multiple spring-web*.jar somewhere? – Biju Kunjummen Oct 09 '12 at 21:56
  • Good call on verifying my dependencies. Unfortunately they are clean, no version mismatches, no conflicts. If you scroll to the right on the log entries it appears that it is in fact finding my DeploymentDescritor class twice (`DeploymentDescriptor`@3b29642c and `DeploymentDescriptor`@432c4c7a) rather than a different `WebApplicationInitializers` implementation. I have several of these applications, and I simple cannot isolate why this one is behaving differently. Thanks again for the thoughts! – node42 Oct 09 '12 at 22:06

3 Answers3

0

The problem here was a Maven Overlay dumping crap a Spring xml configuration file into my application. For whatever reason this caused the WebApplicationInitializer.onStartup() to be called twice. Probably an initialization for the application context, and for the servlet context. Killed off the overlay, application is initializing as expected.

node42
  • 695
  • 4
  • 10
  • 19
  • I have the same problem, how exactly did you "kill Maven Overlay" ? Could you please explain a bit more? I'm looking at http://maven.apache.org/plugins/maven-war-plugin/overlays.html but I'm not sure how to do this? – Leni Kirilov Jun 18 '13 at 13:31
  • It's been a while, but I believe the heart of the issue was the (intentional) usage of Java based Spring configuration class, and the presence of an XML Spring configuration file (unintentional). I don't remember if the xml was context or servlet scoped. Removing the accidentally included (overlayed in my case) xml config file cleared it up for me. Sorry I don't remember the details... – node42 Jul 24 '13 at 19:56
0

I had the same problem. The issue was that I had multiple spring-web*.jar like Biju K. suggested (one as part of the war, the other in shared/tomcat library).

0

I had the same problem. Running mvn clean in the web app module's directory and then starting up Tomcat solved it for me.

Les Hazlewood
  • 18,480
  • 13
  • 68
  • 76