title: Spring controller bean is created in root context AND in servlet context
body: <p>I'm programming a Tomcat application which serves as a proxy for some internal services.</p>
  
  <p>After struggling with some issues (see <a href="https://stackoverflow.com/questions/31983613/implementing-applicationcontextaware-applicationcontext-is-null">ApplicationContext</a> ) , my Tomcat app nearly works as expected.</p>
  
  <p>But the loggings of my app say that the controller bean is initialized twice, and I don't find the reason. I don't use XML configuration, only annotations and Java config.</p>
  
  <p>It seems to me the annotation attribute <code>excludeFilters</code> in the root context is ignored.</p>
  
  <p>See my classes below. web.xml is empty.</p>
  
  <p><strong>spring bootstrap</strong>
  </p>
  
  <pre><code>package com.application.config;
  
  import javax.servlet.*;
  
  import org.springframework.web.WebApplicationInitializer;
  import org.springframework.web.context.ContextLoaderListener;
  import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
  import org.springframework.web.filter.DelegatingFilterProxy;
  import org.springframework.web.servlet.DispatcherServlet;
  
  public class MyAppSpringBoot implements WebApplicationInitializer
  {
  
      @Override
      public void onStartup(ServletContext container) throws ServletException
      {
          initRootContext(container);
  
          initDispatcherContext(container);
  
          addFilters(container);
      }
  
      private void initDispatcherContext(ServletContext container)
      {
          AnnotationConfigWebApplicationContext servletContext = new AnnotationConfigWebApplicationContext();
          servletContext.register(MyAppDispatcherServletContext.class);
          ServletRegistration.Dynamic dispatcher =
                  container.addServlet("myAppDispatcherServlet", new DispatcherServlet(servletContext));
          dispatcher.setLoadOnStartup(1);
          dispatcher.addMapping("/");
      }
  
      private void initRootContext(ServletContext container)
      {
          AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
          rootContext.register(MyAppRootContext.class);
          container.addListener(new ContextLoaderListener(rootContext));
      }
  
      private void addFilters(ServletContext container)
      {
          FilterRegistration.Dynamic registration =
                  container.addFilter("userDbAuthenticationFilter", DelegatingFilterProxy.class);
          registration.addMappingForUrlPatterns(null, false, "/mapgate/*");
  
          registration = container.addFilter("prepareRequestFilter", DelegatingFilterProxy.class);
          registration.addMappingForUrlPatterns(null, false, "/mapgate/*");
  
          registration = container.addFilter("responseTextXmlFilter", DelegatingFilterProxy.class);
          registration.addMappingForUrlPatterns(null, false, "/mapgate/*");
      }
  }
  </code></pre>
  
  <p><strong>root context Java config:</strong></p>
  
  <pre class="lang-java prettyprint-override"><code>package com.application.config;
  
  import java.io.File;
  import java.io.IOException;
  import java.util.Properties;
  import javax.persistence.EntityManagerFactory;
  import javax.sql.DataSource;
  import javax.xml.stream.*;
  
  import org.apache.commons.fileupload.disk.DiskFileItemFactory;
  import org.apache.logging.log4j.LogManager;
  import org.apache.logging.log4j.Logger;
  import org.springframework.context.annotation.*;
  import org.springframework.jdbc.datasource.lookup.DataSourceLookupFailureException;
  import org.springframework.jdbc.datasource.lookup.JndiDataSourceLookup;
  import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
  import org.springframework.stereotype.Controller;
  
  import com.application.controller.MyAppXmlFilterWords;
  import com.application.urlmapping.UrlPairing;
  
  @Configuration
  @ComponentScan(basePackages = "com.application", excludeFilters = @ComponentScan.Filter(Controller.class))
  public class MyAppRootContext
  {
  
      private static Logger logger = LogManager.getLogger(MyAppRootContext.class.getName());
  
      /*
  
      These 3 filter beans are annotated with @Component. They are working as expected
  
      @Bean
      public UserDbAuthenticationFilter userDbAuthenticationFilter()
      {
          return new UserDbAuthenticationFilter();
      }
  
      @Bean
      public PrepareRequestFilter prepareRequestFilter()
      {
          return new PrepareRequestFilter();
      }
  
      @Bean
      public ResponseTextXmlFilter responseTextXmlFilter()
      {
          return new ResponseTextXmlFilter();
      }
  
      */
      @Bean
      public DataSource userDbJpaDataSource() throws DataSourceLookupFailureException
      {
  
          JndiDataSourceLookup lookup = new JndiDataSourceLookup();
          DataSource dataSource = lookup.getDataSource("jdbc/userDbPostgres");
          logger.info("U3R Datasource: {}", dataSource);
          return dataSource;
      }
  
      @Bean
      public EntityManagerFactory entityManagerFactory()
      {
          LocalContainerEntityManagerFactoryBean fb = new LocalContainerEntityManagerFactoryBean();
          fb.setDataSource(userDbJpaDataSource());
          fb.afterPropertiesSet();
          return fb.getNativeEntityManagerFactory();
      }
  
      @Bean
      public DiskFileItemFactory diskFileItemFactory()
      {
          DiskFileItemFactory factory = new DiskFileItemFactory();
          factory.setSizeThreshold(50_000 * 1024);
          factory.setRepository(new File("/WEB-INF/upload"));
          return factory;
      }
  
      @Bean
      public XMLOutputFactory xmlOutputFactory()
      {
          return XMLOutputFactory.newInstance();
      }
  
      @Bean
      public XMLInputFactory xmlInputFactory()
      {
          return XMLInputFactory.newInstance();
      }
  
      @Bean
      public XMLEventFactory xmlEventFactory()
      {
          return XMLEventFactory.newInstance();
      }
  
      @Bean
      public UrlPairing urlPairing() throws IOException
      {
          return new UrlPairing(myAppProperties().getProperty("myApp.UrlPairingFile"));
      }
  
      @Bean
      public Properties myAppProperties() throws IOException
      {
          Properties p = new Properties();
          p.load(MyAppRootContext.class.getResourceAsStream("/myAppConfig.properties"));
          return p;
      }
  
      @Bean
      public MyAppXmlFilterWords xmlFilterWords() throws IOException
      {
          MyAppXmlFilterWords words = MyAppXmlFilterWords.createFilterWords(myAppProperties().getProperty("myApp.xmlFilterWordFile"));
          return words;
      }
  
  }
  </code></pre>
  
  <p><strong>servlet context configuration (no beans here, all in root context)</strong>
  </p>
  
  <pre><code>package com.application.config;
  
  import org.springframework.context.annotation.ComponentScan;
  import org.springframework.context.annotation.Configuration;
  import org.springframework.stereotype.Controller;
  import org.springframework.web.servlet.config.annotation.EnableWebMvc;
  
  /** myApplication Spring dispatcher servlet context
   *
   * Created by ulrich.knaack on 11.08.2015.
   */
  @Configuration
  @EnableWebMvc
  @ComponentScan(basePackages = "com.application.controller", useDefaultFilters = false, includeFilters = @ComponentScan
          .Filter(Controller.class))
  public class MyAppDispatcherServletContext
  {
  // no servlet specific beans required, all in root context
  }
  </code></pre>
  
  <p>controller class
  </p>
  
  <pre><code>package com.application.controller;
  
  import java.io.*;
  import java.net.InetAddress;
  import java.net.UnknownHostException;
  import java.util.*;
  import javax.annotation.PostConstruct;
  import javax.servlet.ServletContext;
  import javax.servlet.ServletException;
  import javax.servlet.http.HttpServletRequest;
  import javax.servlet.http.HttpServletResponse;
  
  import org.apache.commons.fileupload.FileItem;
  import org.apache.commons.fileupload.FileUploadException;
  import org.apache.commons.fileupload.disk.DiskFileItem;
  import org.apache.commons.fileupload.disk.DiskFileItemFactory;
  import org.apache.commons.fileupload.servlet.ServletFileUpload;
  import org.apache.commons.lang3.StringUtils;
  import org.apache.commons.lang3.exception.ExceptionUtils;
  import org.apache.http.*;
  import org.apache.http.client.ClientProtocolException;
  import org.apache.http.client.config.RequestConfig;
  import org.apache.http.client.methods.*;
  import org.apache.http.entity.*;
  import org.apache.http.entity.mime.MultipartEntityBuilder;
  import org.apache.http.impl.client.CloseableHttpClient;
  import org.apache.http.impl.client.HttpClients;
  import org.apache.logging.log4j.LogManager;
  import org.apache.logging.log4j.Logger;
  import org.springframework.beans.BeansException;
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.context.ApplicationContext;
  import org.springframework.context.ApplicationContextAware;
  import org.springframework.stereotype.Controller;
  import org.springframework.web.bind.annotation.RequestMapping;
  import org.springframework.web.bind.annotation.RequestMethod;
  
  import com.application.filter.MyAppRequestHelper;
  import com.application.misc.MyAppHttpTools;
  
  import static com.application.misc.MyAppConstants.*;
  
  @Controller
  @RequestMapping(value = "mapgate/**")
  public class MyAppProxyController implements ApplicationContextAware
  {
      private static final Logger logger = LogManager.getLogger(MyAppProxyController.class.getName());
  
      @Autowired
      Properties myAppProperties;
  
      @Autowired
      private DiskFileItemFactory diskFileItemFactory;
  
      private ApplicationContext appContext;
  
      @PostConstruct
      public void init() throws ServletException
      {
          requestLogIntervall = (Integer.parseInt(myAppProperties.getProperty("myApp.requestLogIntervall")));
          logger.debug("Controller {} initialisiert. App-Context: {} {}", this.getClass().getName(),
                  appContext.hashCode(), appContext);
  
          logger.debug("Beans im Zugriff von Controller:");
          for (String beanName : appContext.getBeanDefinitionNames())
          {
              logger.debug("          {}", beanName);
          }
  
          MyAppProxyController controller = (MyAppProxyController) appContext.getBean("myAppProxyController");
          logger.debug("controller-hash im Controller={}", controller.hashCode());
      }
  
      @SuppressWarnings("TryFinallyCanBeTryWithResources")
      @RequestMapping(method = RequestMethod.POST)
      protected void doPost(HttpServletRequest customerRequest,
                            HttpServletResponse response) throws ServletException,
              IOException
      {
      // some code
      }
  
      @RequestMapping(method = RequestMethod.GET)
      protected void doGet(HttpServletRequest customerRequest, HttpServletResponse customerResponse)
      {
      // some code
      }
  
      @Override
      public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
      {
          appContext = applicationContext;
      }
  
  }
  </code></pre>
  
  <p><strong>Logging</strong></p>
  
  <pre><code>20150814-165337 INFO  [RMI TCP Connection(5)-127.0.0.1] Root WebApplicationContext: initialization started
  20150814-165337 INFO  [RMI TCP Connection(5)-127.0.0.1] Refreshing Root WebApplicationContext: startup date [Fri Aug 14 16:53:37 CEST 2015]; root of context hierarchy
  20150814-165337 INFO  [RMI TCP Connection(5)-127.0.0.1] Registering annotated classes: [class com.application.config.MyAppRootContext]
  20150814-165337 INFO  [RMI TCP Connection(5)-127.0.0.1] URL-Paring Konstruktor, Datei D:/doorman-ent/doorman-conf/urlpairing.txt
  20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1] URL-Paare aus Datei &lt;D:/doorman-ent/doorman-conf/urlpairing.txt&gt; lesen...
  20150814-165337 INFO  [RMI TCP Connection(5)-127.0.0.1] URL-Pairing: es existieren 17 Service-Paar(e) und 2 File-Paar(e)
  20150814-165337 INFO  [RMI TCP Connection(5)-127.0.0.1] Filter com.application.filter.PrepareRequestFilter initialisiert. App-Context: 615649080 Root WebApplicationContext: startup date [Fri Aug 14 16:53:37 CEST 2015]; root of context hierarchy
  20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1] Konstruktor com.application.filter.ResponseTextXmlFilter
  20150814-165337 INFO  [RMI TCP Connection(5)-127.0.0.1] Filter com.application.filter.ResponseTextXmlFilter initialisiert. App-Context: 615649080 Root WebApplicationContext: startup date [Fri Aug 14 16:53:37 CEST 2015]; root of context hierarchy
  20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1] Beans im Zugriff von XMLFilter:
  20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           org.springframework.context.annotation.internalConfigurationAnnotationProcessor
  20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           org.springframework.context.annotation.internalAutowiredAnnotationProcessor
  20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           org.springframework.context.annotation.internalRequiredAnnotationProcessor
  20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           org.springframework.context.annotation.internalCommonAnnotationProcessor
  20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           org.springframework.context.annotation.internalPersistenceAnnotationProcessor
  20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           org.springframework.context.event.internalEventListenerProcessor
  20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           org.springframework.context.event.internalEventListenerFactory
  20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           myAppRootContext
  20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor
  20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           org.springframework.context.annotation.ConfigurationClassPostProcessor.enhancedConfigurationProcessor
  20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           myAppDispatcherServletContext
  20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           prepareRequestFilter
  20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           responseTextXmlFilter
  20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           userDbAuthenticationFilter
  20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           myAppProxyController
  20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration
  20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           requestMappingHandlerMapping
  20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           mvcContentNegotiationManager
  20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           viewControllerHandlerMapping
  20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           beanNameHandlerMapping
  20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           resourceHandlerMapping
  20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           mvcResourceUrlProvider
  20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           defaultServletHandlerMapping
  20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           requestMappingHandlerAdapter
  20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           mvcConversionService
  20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           mvcValidator
  20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           mvcPathMatcher
  20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           mvcUrlPathHelper
  20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           mvcUriComponentsContributor
  20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           httpRequestHandlerAdapter
  20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           simpleControllerHandlerAdapter
  20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           handlerExceptionResolver
  20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           mvcViewResolver
  20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           diskFileItemFactory
  20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           entityManagerFactory
  20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           urlPairing
  20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           myAppProperties
  20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           xmlInputFactory
  20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           userDbJpaDataSource
  20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           xmlFilterWords
  20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           xmlOutputFactory
  20150814-165337 DEBUG [RMI TCP Connection(5)-127.0.0.1]           xmlEventFactory
  20150814-165338 DEBUG [RMI TCP Connection(5)-127.0.0.1] Controller com.application.controller.MyAppProxyController initialisiert. App-Context: 615649080 Root WebApplicationContext: startup date [Fri Aug 14 16:53:37 CEST 2015]; root of context hierarchy
  20150814-165338 DEBUG [RMI TCP Connection(5)-127.0.0.1] controller-hash im Controller=1369268001
  20150814-165338 DEBUG [RMI TCP Connection(5)-127.0.0.1] controller-hash im XMLFilter=1369268001
  20150814-165338 INFO  [RMI TCP Connection(5)-127.0.0.1] U3R Datasource: org.apache.tomcat.dbcp.dbcp2.BasicDataSource@7c912e88
  20150814-165338 INFO  [RMI TCP Connection(5)-127.0.0.1] Building JPA container EntityManagerFactory for persistence unit 'userDbPersistence'
  20150814-165339 INFO  [RMI TCP Connection(5)-127.0.0.1] Filter com.application.filter.UserDbAuthenticationFilter initialisiert. App-Context: 615649080 Root WebApplicationContext: startup date [Fri Aug 14 16:53:37 CEST 2015]; root of context hierarchy
  20150814-165339 DEBUG [RMI TCP Connection(5)-127.0.0.1] EntityManagerFactory: org.hibernate.jpa.internal.EntityManagerFactoryImpl@6567e35f
  20150814-165340 INFO  [RMI TCP Connection(5)-127.0.0.1] Mapped "{[/mapgate/**],methods=[GET]}" onto protected void com.application.controller.MyAppProxyController.doGet(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
  20150814-165340 INFO  [RMI TCP Connection(5)-127.0.0.1] Mapped "{[/mapgate/**],methods=[POST]}" onto protected void com.application.controller.MyAppProxyController.doPost(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) throws javax.servlet.ServletException,java.io.IOException
  20150814-165340 INFO  [RMI TCP Connection(5)-127.0.0.1] Looking for @ControllerAdvice: Root WebApplicationContext: startup date [Fri Aug 14 16:53:37 CEST 2015]; root of context hierarchy
  20150814-165340 INFO  [RMI TCP Connection(5)-127.0.0.1] Root WebApplicationContext: initialization completed in 2831 ms
  20150814-165340 INFO  [RMI TCP Connection(5)-127.0.0.1] FrameworkServlet 'myAppDispatcherServlet': initialization started
  20150814-165340 INFO  [RMI TCP Connection(5)-127.0.0.1] Refreshing WebApplicationContext for namespace 'myAppDispatcherServlet-servlet': startup date [Fri Aug 14 16:53:40 CEST 2015]; parent: Root WebApplicationContext
  20150814-165340 INFO  [RMI TCP Connection(5)-127.0.0.1] Registering annotated classes: [class com.application.config.MyAppDispatcherServletContext]
  20150814-165340 DEBUG [RMI TCP Connection(5)-127.0.0.1] Controller com.application.controller.MyAppProxyController initialisiert. App-Context: 332892020 WebApplicationContext for namespace 'myAppDispatcherServlet-servlet': startup date [Fri Aug 14 16:53:40 CEST 2015]; parent: Root WebApplicationContext
  20150814-165340 DEBUG [RMI TCP Connection(5)-127.0.0.1] controller-hash im Controller=1145466717
  20150814-165340 INFO  [RMI TCP Connection(5)-127.0.0.1] Mapped "{[/mapgate/**],methods=[GET]}" onto protected void com.application.controller.MyAppProxyController.doGet(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
  20150814-165340 INFO  [RMI TCP Connection(5)-127.0.0.1] Mapped "{[/mapgate/**],methods=[POST]}" onto protected void com.application.controller.MyAppProxyController.doPost(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) throws javax.servlet.ServletException,java.io.IOException
  20150814-165340 INFO  [RMI TCP Connection(5)-127.0.0.1] Looking for @ControllerAdvice: WebApplicationContext for namespace 'myAppDispatcherServlet-servlet': startup date [Fri Aug 14 16:53:40 CEST 2015]; parent: Root WebApplicationContext
  20150814-165340 INFO  [RMI TCP Connection(5)-127.0.0.1] FrameworkServlet 'myAppDispatcherServlet': initialization completed in 86 ms
  20150814-165340 WARN  [http-apr-8080-exec-4] No mapping found for HTTP request with URI [/doorman/] in DispatcherServlet with name 'myAppDispatcherServlet'
  20150814-165341 WARN  [http-apr-8080-exec-10] No mapping found for HTTP request with URI [/doorman/] in DispatcherServlet with name 'myAppDispatcherServlet'
  </code></pre>