title: Spring MVC & Security 3.2 with JavaConfig - WebApplicationContext being initialized, destroyed, initialized again
body: <p>This week I switched my entire webapp from xml config to JavaConfig.  I've noticed some odd behaviors.  I'm using Netbeans with integrated tomcat.  When I deploy my app, I notice this in the logs:</p>
  
  <pre><code>Mar 13, 2014 7:55:48 AM org.apache.catalina.core.ApplicationContext log
  INFO: Spring WebApplicationInitializers detected on classpath: [x.configuration.SecurityInitializer@703f4126, x.configuration.WebAppInitializer@48ce5f5c]
  Mar 13, 2014 7:55:49 AM org.apache.catalina.core.ApplicationContext log
  INFO: Initializing Spring root WebApplicationContext
  Mar 13, 2014 7:56:20 AM org.apache.catalina.core.ApplicationContext log
  INFO: Initializing Spring FrameworkServlet 'dispatcher'
  Mar 13, 2014 7:56:55 AM org.apache.catalina.core.ApplicationContext log
  INFO: Destroying Spring FrameworkServlet 'dispatcher'
  Mar 13, 2014 7:56:55 AM org.apache.catalina.core.ApplicationContext log
  INFO: Closing Spring root WebApplicationContext
  Mar 13, 2014 7:57:04 AM org.apache.catalina.core.ApplicationContext log
  INFO: Spring WebApplicationInitializers detected on classpath: [x.configuration.SecurityInitializer@5379ce53, x.configuration.WebAppInitializer@61d8d5f5]
  Mar 13, 2014 7:57:05 AM org.apache.catalina.core.ApplicationContext log
  INFO: Initializing Spring root WebApplicationContext
  Mar 13, 2014 7:57:33 AM org.apache.catalina.core.ApplicationContext log
  INFO: Initializing Spring FrameworkServlet 'dispatcher'
  </code></pre>
  
  <p>There are other things that are running twice as well... I have a class that listens for ContextRefreshedEvents in my dispatcher servlet context.  When I debug the web app, I see log statements as if this code is being executed, yet it never hits any breakpoints I have set up... the first time.  After that mystery context seems to completely initialize and then apparently gets destroyed, it gets initialized again.  This time, my breakpoints get hit and I can step through my code.  I <em>THINK</em> all of my configuration files are configured right based on everything I've read, and I have my root/dispatcher component scans mutually exclusive and not scanning the same packages.</p>
  
  <p>This is becoming a bigger issue because now I'm trying to setup a BCryptPasswordEncoder. I'm having issues eerily similar to what I described above -- I am no longer able to debug or see logging statements from my CustomAuthenticationProvider, although I am from my CustomUserDetailsService.  I'm starting to think somehow it's using a cached instance of my CustomAuthenticationProvider from that initial ghost context that got created or something.  Any help figuring this out would be appreciated.</p>
  
  <p>My packages are set up pretty flat, ie: x.controllers, x.services, x.domain, x.dao, x.configuration, etc, so I have to use some excludeFilters to make sure the right contexts are scanning the right components.  Anyway, here is my config:</p>
  
  <p>AbstractAnnotationConfigDispatcherServletInitializer:</p>
  
  <pre><code>public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
  
      @Override
      protected Class&lt;?&gt;[] getRootConfigClasses() {
          return new Class[]{ SecurityConfig.class, ServiceConfig.class, PersistenceConfig.class, Log4jConfig.class };
      }
  
      @Override
      protected Class&lt;?&gt;[] getServletConfigClasses() {
          return new Class[]{SpringMvcConfig.class, Initializer.class};
      }
  
      @Override
      protected String[] getServletMappings() {
          return new String[]{
              "/rest/*",
              "/index.html",
              "/login.html",
              "/admin.html",
              "/index/*",
              "/login/*",
              "/admin/*"
          };
      }
  
      @Override
      protected Filter[] getServletFilters() {
          CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
          characterEncodingFilter.setEncoding("UTF-8");
          characterEncodingFilter.setForceEncoding(true);
  
          OpenEntityManagerInViewFilter openEntityManagerInViewFilter = new OpenEntityManagerInViewFilter();
          openEntityManagerInViewFilter.setBeanName("openEntityManagerInViewFilter");
          openEntityManagerInViewFilter.setPersistenceUnitName("HSQL");
  
          return new javax.servlet.Filter[]{characterEncodingFilter, openEntityManagerInViewFilter};
      }
  }
  </code></pre>
  
  <p>Service config:</p>
  
  <pre><code>@Configuration
  @ComponentScan(basePackages = "x",
          excludeFilters = {
              @ComponentScan.Filter(type = FilterType.ANNOTATION, value = Controller.class),
              @ComponentScan.Filter(type = FilterType.ANNOTATION, value = Configuration.class)
          }
  )
  public class ServiceConfig {
  
      @Bean
      public DefaultAnnotationHandlerMapping defaultAnnotationHandlerMapping() {
          DefaultAnnotationHandlerMapping handlerMapping = new DefaultAnnotationHandlerMapping();
          handlerMapping.setAlwaysUseFullPath(true);
          handlerMapping.setDetectHandlersInAncestorContexts(true);
          return handlerMapping;
      }
  }
  </code></pre>
  
  <p>Security initializer:</p>
  
  <pre><code>@Order(1)
  public class SecurityInitializer extends AbstractSecurityWebApplicationInitializer {}
  </code></pre>
  
  <p>Security config:</p>
  
  <pre><code>@Configuration
  @EnableWebMvcSecurity
  @EnableGlobalMethodSecurity(prePostEnabled = true)
  public class SecurityConfig extends WebSecurityConfigurerAdapter {
  
      @Autowired
      private CustomUserDetailsService userDetailsService;
      @Autowired
      private CustomAuthenticationProvider customAuthenticationProvider;
  
      @Autowired
      public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
          auth.userDetailsService(userDetailsService);
      }
  
      @Override
      protected void configure(HttpSecurity http) throws Exception {
          AuthenticationProvider rememberMeAuthenticationProvider = rememberMeAuthenticationProvider();
          TokenBasedRememberMeServices tokenBasedRememberMeServices = tokenBasedRememberMeServices();
  
          List&lt;AuthenticationProvider&gt; authenticationProviders = new ArrayList&lt;AuthenticationProvider&gt;(2);
          authenticationProviders.add(rememberMeAuthenticationProvider);
          authenticationProviders.add(customAuthenticationProvider);
          AuthenticationManager authenticationManager = authenticationManager(authenticationProviders);
  
          http
                  .csrf().disable()
                  .headers().disable()
                  .addFilter(new RememberMeAuthenticationFilter(authenticationManager, tokenBasedRememberMeServices))
                  .rememberMe().rememberMeServices(tokenBasedRememberMeServices)
                  .and()
                  .authorizeRequests()
                  .antMatchers("/js/**", "/css/**", "/img/**", "/login", "/processLogin").permitAll()
                  .antMatchers("/index.jsp", "/index.html", "/index").hasRole("USER")
                  .antMatchers("/admin", "/admin.html", "/admin.jsp", "/js/saic/jswe/admin/**").hasRole("ADMIN")
                  .and()
                  .formLogin().loginProcessingUrl("/processLogin").loginPage("/login").permitAll()
                  .and().exceptionHandling().accessDeniedPage("/login").and()
                  .logout().permitAll();
      }
  
      @Override
      public void configure(WebSecurity web) throws Exception {
          web.ignoring().antMatchers("/js/**", "/css/**", "/img/**");
      }
  
      @Bean
      public BCryptPasswordEncoder bCryptPasswordEncoder() {
          return new BCryptPasswordEncoder();
      }
  
      @Bean
      public AuthenticationManager authenticationManager(List&lt;AuthenticationProvider&gt; authenticationProviders) {
          return new ProviderManager(authenticationProviders);
      }
  
      @Bean
      public TokenBasedRememberMeServices tokenBasedRememberMeServices() {
          return new TokenBasedRememberMeServices("testKey", userDetailsService);
      }
  
      @Bean
      public AuthenticationProvider rememberMeAuthenticationProvider() {
          return new org.springframework.security.authentication.RememberMeAuthenticationProvider("testKey");
      }
  
      protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
          auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
      }
  }
  </code></pre>
  
  <p>MVC config:</p>
  
  <pre><code>@Configuration
  @EnableWebMvc
  @EnableTransactionManagement
  @ComponentScan(basePackages = "x.controllers")
  public class SpringMvcConfig extends WebMvcConfigurerAdapter {
  
      @Override
      public void configureMessageConverters(List&lt;HttpMessageConverter&lt;?&gt;&gt; converters) {
          converters.add(mappingJacksonHttpMessageConverter());
          converters.add(marshallingMessageConverter());
          super.configureMessageConverters(converters);
      }
  
      @Bean
      public InternalResourceViewResolver setupViewResolver() {
          InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
          viewResolver.setViewClass(JstlView.class);
          viewResolver.setPrefix("/WEB-INF/jsp/");
          viewResolver.setSuffix(".jsp");
          return viewResolver;
      }
  
      @Bean
      public JacksonAnnotationIntrospector jacksonAnnotationIntrospector() {
          return new JacksonAnnotationIntrospector();
      }
  
      @Bean
      public ObjectMapper objectMapper() {
          ObjectMapper mapper = new ObjectMapper();
          mapper.setAnnotationIntrospector(jacksonAnnotationIntrospector());
          mapper.registerModule(new JodaModule());
          mapper.registerModule(new Hibernate4Module());
          return mapper;
      }
  
      @Bean
      public MappingJackson2HttpMessageConverter mappingJacksonHttpMessageConverter() {
          MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
          messageConverter.setObjectMapper(objectMapper());
          return messageConverter;
      }
  
      @Bean(name = "marshaller")
      public Jaxb2Marshaller jaxb2Marshaller() {
          Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
          marshaller.setContextPath("some.path");
          return marshaller;
      }
  
      @Bean
      public MarshallingHttpMessageConverter marshallingMessageConverter() {
          return new MarshallingHttpMessageConverter(
                  jaxb2Marshaller(),
                  jaxb2Marshaller()
          );
      }
  }
  </code></pre>
  
  <p>My context refreshed listener:</p>
  
  <pre><code>@Component
  @Configuration
  public class Initializer implements ApplicationListener&lt;ContextRefreshedEvent&gt;
  {
  
      @Override
      public void onApplicationEvent(ContextRefreshedEvent e) {
          &lt;do some intialization stuff between several services/daos after spring is done building everything&gt;
      }
  }
  </code></pre>
  
  <p>I'll leave out my persistence and logging config as I don't believe it's relevant... my PersistenceConfig class is annotated with: </p>
  
  <pre><code>@Configuration
  @EnableTransactionManagement
  @PropertySource("classpath:database.properties")
  </code></pre>
  
  <p>and Log4jConfig is annotated with:</p>
  
  <pre><code>@Order(2)
  @Configuration
  </code></pre>
  
  <p>One thing you might note as odd is that I have my Initializer implements ApplicationListener class annotated with @Configuration.  I did this simply so the root ServiceConfig won't pick it up during it's component scan and it will only be created in the dispatcher servlet context.</p>
  
  <p>After much pain and anguish, I'm thinking the problem isn't specifically my Spring config, but something I'm missing with the AbstractAnnotationConfigDispatcherServletInitializer class... somehow, someway, something is making it double down on it's work.  Should I be overriding protected WebApplicationContext createRootApplicationContext() or public void onStartup(ServletContext servletContext) throws ServletException or something to manually create the contexts?</p>
  
  <p><strong>UPDATE</strong></p>
  
  <p>I had an inkling of a suspicion that using both the WebApplicationInitializer that AbstractAnnotationConfigDispatcherServletInitializer extends from and the WebApplicationListener that AbstractSecurityWebApplicationInitializer extends from was the root cause of this.  Even though I knew it would cause spring security to fail because it wasn't registering the spring security filter chain, I decided to remove this class to see if it would fix the problem -- no difference.</p>
  
  <p>Out of frustration I decided to download glassfish and deploy it there.  The very first time I deployed it, it only ran through once!  It deployed, but obviously, I wasn't able to sign in as spring security was now broken.  As a test, I re-add the class "public class SecurityInitializer extends AbstractSecurityWebApplicationInitializer {}" to see what would happen.  As I really expected, the problem resurfaced.  Everything ran through twice.  SO, I removed it again, and now I'm stuck with the exact same problem.  It's still building the context, running through my initialization, destroying the context, then doing it all over again.  It's like that second registered WebApplicationInitializer is getting stuck or cached in the web servers somehow.  That's the only explanation I can think of.... So I'm close to an answer now, but I'm still not sure how to solve this...</p>