title: WebApplicationContext not being shut down on Servlet Context reload
body: <p>When I shut down Tomcat, I observe a correct shutdown and cleanup of the Spring WebApplicationContext. However, when I redeploy my Spring-based WAR (by copying the new WAR to <code>webapps</code>), normal shutdown does not occur. This is a problem for me due to all the ensuing resource leaks:</p>
  <pre><code>org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
  SEVERE: The web application [] appears to have started a thread named [hz.hazelcast-swipe-instance.scheduled] but has failed to stop it. This is very likely to create a memory leak.
  org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
  SEVERE: The web application [] appears to have started a thread named [hz.hazelcast-swipe-instance.operation.thread-0] but has failed to stop it. This is very likely to create a memory leak.
  </code></pre>
  <p>... and many more. I am using XML-less configuration, this is my WebApplicationInitializer:</p>
  <pre><code>public class WebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer
  {
    @Override protected Class&lt;?&gt;[] getRootConfigClasses() {
      return new Class[] { WebSecurityConfig.class, WebMvcConfig.class };
    }
    @Override protected Class&lt;?&gt;[] getServletConfigClasses() { return null; }
  
    @Override protected String[] getServletMappings() { return new String[] { &quot;/&quot; }; }
  
    @Override public void onStartup(ServletContext ctx) throws ServletException {
      ctx.setInitParameter(&quot;spring.profiles.active&quot;, &quot;production&quot;);
      super.onStartup(ctx);
    }
  }
  </code></pre>
  <p>There is no configuration specific to controlling the behavior upon servlet context reload, and I assume this should have worked out of the box.</p>
  <p>Is there a way to make the WebApplicationContext close properly before continuing the servlet context reloading procedure?</p>
  <p>I am on Spring 4.0.5, Tomcat 7.0.54, Hazelcast 3.2.1, Hibernate 4.3.4.Final.</p>
  <h2>Update</h2>
  <p>I have added a Spring application listener for the ContextClosedEvent and printed the stack trace of its invocation:</p>
  <pre><code>    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:333) [spring-context-4.0.6.RELEASE.jar:4.0.6.RELEASE]
      at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:335) [spring-context-4.0.6.RELEASE.jar:4.0.6.RELEASE]
      at org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:880) [spring-context-4.0.6.RELEASE.jar:4.0.6.RELEASE]
      at org.springframework.context.support.AbstractApplicationContext.close(AbstractApplicationContext.java:841) [spring-context-4.0.6.RELEASE.jar:4.0.6.RELEASE]
      at org.springframework.web.servlet.FrameworkServlet.destroy(FrameworkServlet.java:819) [spring-webmvc-4.0.6.RELEASE.jar:4.0.6.RELEASE]
      at org.apache.catalina.core.StandardWrapper.unload(StandardWrapper.java:1486) [catalina.jar:7.0.54]
      at org.apache.catalina.core.StandardWrapper.stopInternal(StandardWrapper.java:1847) [catalina.jar:7.0.54]
      at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:232) [catalina.jar:7.0.54]
      at org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5647) [catalina.jar:7.0.54]
      at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:232) [catalina.jar:7.0.54]
      at org.apache.catalina.core.ContainerBase$StopChild.call(ContainerBase.java:1575) [catalina.jar:7.0.54]
      at org.apache.catalina.core.ContainerBase$StopChild.call(ContainerBase.java:1564) [catalina.jar:7.0.54]
  </code></pre>
  <p>This indicates that the Spring shutdown occurs in its <code>Servlet#destroy</code> method. This is the relevant snippet from <code>AbstractApplicationContext#close()</code>:</p>
  <pre><code>        if (logger.isInfoEnabled()) {
              logger.info(&quot;Closing &quot; + this);
          }
  
          LiveBeansView.unregisterApplicationContext(this);
  
          try {
              // Publish shutdown event.
              publishEvent(new ContextClosedEvent(this));
          }
          catch (Throwable ex) {
              logger.warn(&quot;Exception thrown from ApplicationListener handling ContextClosedEvent&quot;, ex);
          }
          // Stop all Lifecycle beans, to avoid delays during individual destruction.
          try {
              getLifecycleProcessor().onClose();
          }
          catch (Throwable ex) {
              logger.warn(&quot;Exception thrown from LifecycleProcessor on context close&quot;, ex);
          }
  
          // Destroy all cached singletons in the context's BeanFactory.
          destroyBeans();
  
          // Close the state of this context itself.
          closeBeanFactory();
  
          // Let subclasses do some final clean-up if they wish...
          onClose();
  
          synchronized (this.activeMonitor) {
              this.active = false;
          }
  </code></pre>
  <p>I see the log entry from the start of this snippet, and I get my ContextClosedEvent. I also see an entry <code>DefaultLifecycleProcessor - Stopping beans in phase 2147483647</code>, which probably comes from the <code>getLifecycleProcessor.onClose()</code> line. It seems that some error occurs downstream from that. Some exception may be swallowed.</p>
  <h2>Update 2</h2>
  <p>As requested, this is how I configure Hazelcast:</p>
  <pre><code>@Bean(destroyMethod=&quot;shutdown&quot;) public HazelcastInstance hazelcast() {
    final Config c = hzConfig();
    final JoinConfig join = c.getNetworkConfig().getJoin();
    join.getMulticastConfig().setEnabled(false);
    join.getTcpIpConfig().setEnabled(true);
    return getOrCreateHazelcastInstance(c);
  }
  </code></pre>
  <p><code>hzConfig()</code> is a method where instance name, group name and password, map names, and map indices are configured, so I don't think it is of interest here.</p>
  <p>And this is my Hibernate SessionFactory config:</p>
  <pre><code>@Bean
  public LocalSessionFactoryBean sessionFactory() {
    final LocalSessionFactoryBean b = new LocalSessionFactoryBean();
    b.setDataSource(dataSource);
    b.setHibernateProperties(props(
        &quot;hibernate.connection.release_mode&quot;, &quot;on_close&quot;,
        &quot;hibernate.id.new_generator_mappings&quot;, &quot;true&quot;,
        &quot;hibernate.hbm2ddl.auto&quot;, &quot;update&quot;,
        &quot;hibernate.order_inserts&quot;, &quot;true&quot;,
        &quot;hibernate.order_updates&quot;, &quot;true&quot;,
        &quot;hibernate.max_fetch_depth&quot;, &quot;0&quot;,
        &quot;hibernate.jdbc.fetch_size&quot;, &quot;200&quot;,
        &quot;hibernate.jdbc.batch_size&quot;, &quot;50&quot;,
        &quot;hibernate.jdbc.batch_versioned_data&quot;, &quot;true&quot;,
        &quot;hibernate.jdbc.use_streams_for_binary&quot;, &quot;true&quot;,
        &quot;hibernate.use_sql_comments&quot;, &quot;true&quot;
    ));
    return b;
  }
  </code></pre>