title: How to configure several child context in a Spring Boot 2 application?
body: <p>To learn more about multiple contexts usage in a same application I decided to create a very basic example application managing post resources and using 2 child contexts : one for Rest API and the other one for MVC.</p>
  <p>The application is deployed in a separate Tomcat 8.5 server and is listening on port 8081.</p>
  <p>Here's the <code>multi-context</code> application structure :</p>
  <ul>
  <li>multi-context
  <ul>
  <li>app
  <ul>
  <li>Post.java</li>
  <li>PostService.java</li>
  <li>MultiContextApplication.java</li>
  </ul>
  </li>
  <li>api
  <ul>
  <li>ApiConfig.java</li>
  <li>PostApiController.java</li>
  </ul>
  </li>
  <li>mvc
  <ul>
  <li>MvcConfig.java</li>
  <li>PostController.java</li>
  </ul>
  </li>
  </ul>
  </li>
  </ul>
  <p><strong>1) Api package (first child context)</strong></p>
  <p><em>ApiConfig.java</em></p>
  <pre><code>@Configuration
  @EnableWebMvc
  @ComponentScan
  public class ApiConfig {
  
  }
  </code></pre>
  <p>Only responsible of the loading of the <code>PostApiController</code> in API child context</p>
  <p><em>PostApiController.java</em></p>
  <pre><code>@RestController
  @AllArgsConstructor
  @RequestMapping(&quot;/posts&quot;)
  public class PostApiController {
  
      private final PostService postService;
  
      @PostMapping
      public ResponseEntity&lt;Post&gt; createPost(@RequestBody Post post) {
          return ok(postService.createPost(post.getTitle(), post.getContent()));
      }
  
      @GetMapping
      public ResponseEntity&lt;List&lt;Post&gt;&gt; getAllPosts() {
          return ok(postService.getAllPosts());
      }
  }
  </code></pre>
  <p><strong>2) Mvc package (second sibling context)</strong></p>
  <p><em>MvcConfig.java</em></p>
  <pre><code>@Configuration
  @EnableWebMvc
  @ComponentScan
  public class MvcConfig {
  
  }
  </code></pre>
  <p>Only responsible of the loading of the MVC <code>PostController</code> in MVC child context</p>
  <p><em>PostController.java</em></p>
  <pre><code>@Controller
  @AllArgsConstructor
  @RequestMapping(&quot;/posts&quot;)
  public class PostController {
  
      private final PostService postService;
  
      @GetMapping
      public ModelAndView getAllPostsView() {
          Map&lt;String, Object&gt; values = new HashMap&lt;&gt;();
          values.put(&quot;posts&quot;, postService.getAllPosts());
          return new ModelAndView(&quot;posts&quot;, values);
      }
  }
  </code></pre>
  <p><strong>3) App package (root application context)</strong></p>
  <p>Package responsible of the initialization of the root application context (loading of common beans (PostService) sharable in every child context) and the initialization of the 2 children contexts (API and MVC).</p>
  <p><em>MultiContextApplication.java</em></p>
  <pre><code>@SpringBootApplication
  public class MultiContextApplication extends SpringBootServletInitializer {
  
      public static void main(String[] args) {
          SpringApplication.run(MultiContextApplication.class, args);
      }
  
      /**
       * Root context initialization
       */
      @Override
      protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
          return application.sources(MultiContextApplication.class);
      }
  
      /**
       * Rest API dispatcher servlet initialization
       */
      @Bean(name = &quot;apiDispatcherServlet&quot;)
      public DispatcherServlet apiDispatcherServlet(WebApplicationContext webApplicationContext) {
          AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();
          applicationContext.setParent(webApplicationContext);
          applicationContext.register(ApiConfig.class);
          DispatcherServlet dispatcherServlet = new DispatcherServlet();
          dispatcherServlet.setApplicationContext(applicationContext);
          return dispatcherServlet;
      }
  
      /**
       * Rest API child context initialization
       */
      @Bean(name = &quot;apiServletRegistrationBean&quot;)
      public ServletRegistrationBean apiServletRegistrationBean(
              @Qualifier(&quot;apiDispatcherServlet&quot;) DispatcherServlet apiDispatcherServlet) {
          ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean();
          servletRegistrationBean.addUrlMappings(&quot;/api/*&quot;);
          servletRegistrationBean.setServlet(apiDispatcherServlet);
          servletRegistrationBean.setLoadOnStartup(1);
          servletRegistrationBean.setName(&quot;api-servlet&quot;);
          return servletRegistrationBean;
      }
  
      /**
       * MVC dispatcher servlet initialization
       */
      @Bean(name = &quot;mvcDispatcherServlet&quot;)
      public DispatcherServlet mvcDispatcherServlet(WebApplicationContext webApplicationContext) {
          AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();
          applicationContext.setParent(webApplicationContext);
          applicationContext.register(MvcConfig.class);
          DispatcherServlet dispatcherServlet = new DispatcherServlet();
          dispatcherServlet.setApplicationContext(applicationContext);
          return dispatcherServlet;
      }
  
      /**
       * MVC child context initialization
       */
      @Bean(name = &quot;mvcServletRegistrationBean&quot;)
      public ServletRegistrationBean mvcServletRegistrationBean(
              @Qualifier(&quot;mvcDispatcherServlet&quot;) DispatcherServlet mvcDispatcherServlet) {
          ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean();
          servletRegistrationBean.addUrlMappings(&quot;/mvc/*&quot;);
          servletRegistrationBean.setServlet(mvcDispatcherServlet);
          servletRegistrationBean.setLoadOnStartup(1);
          servletRegistrationBean.setName(&quot;mvc-servlet&quot;);
          return servletRegistrationBean;
      }
  }
  </code></pre>
  <p>As we can expect if the incoming request is <em>http://localhost:8081/multi-context/api/posts</em> it will be treated by the <code>apiDispatcherServlet</code> (urlMapping = /api/*) and if the incoming request is <em>http://localhost:8081/multi-context/mvc/posts</em> it will be treated the <code>mvcDispatcherServlet</code> (urlMapping = /mvc/*).</p>
  <p>The problem is I have a <code>404</code> for both cases and I really don't understand why.</p>
  <pre><code>GET http://localhost:8081/multi-context/api/posts
  {
      &quot;timestamp&quot;: &quot;2020-07-14T00:28:33.461+00:00&quot;,
      &quot;status&quot;: 404,
      &quot;error&quot;: &quot;Not Found&quot;,
      &quot;message&quot;: &quot;&quot;,
      &quot;path&quot;: &quot;/multi-context/api/posts&quot;
  }
  </code></pre>
  <p>Output log :</p>
  <pre><code>2020-07-14 02:46:01.203  INFO 11120 --- [on(3)-127.0.0.1] c.i.m.app.MultiContextApplication        : Starting MultiContextApplication v0.0.1-SNAPSHOT on L-5CD9474WTJ with PID 11120
  2020-07-14 02:46:01.207  INFO 11120 --- [on(3)-127.0.0.1] c.i.m.app.MultiContextApplication        : No active profile set, falling back to default profiles: default
  2020-07-14 02:46:02.162  INFO 11120 --- [on(3)-127.0.0.1] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 919 ms
  2020-07-14 02:46:02.626  INFO 11120 --- [on(3)-127.0.0.1] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
  2020-07-14 02:46:02.771  INFO 11120 --- [on(3)-127.0.0.1] o.s.b.a.w.s.WelcomePageHandlerMapping    : Adding welcome page template: index
  2020-07-14 02:46:02.904  INFO 11120 --- [on(3)-127.0.0.1] c.i.m.app.MultiContextApplication        : Started MultiContextApplication in 2.253 seconds (JVM running for 4.955)
  2020-07-14 02:46:03.003  INFO 11120 --- [on(3)-127.0.0.1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'api-servlet'
  2020-07-14 02:46:03.084  INFO 11120 --- [on(3)-127.0.0.1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 81 ms
  2020-07-14 02:46:03.086  INFO 11120 --- [on(3)-127.0.0.1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'mvc-servlet'
  2020-07-14 02:46:03.138  INFO 11120 --- [on(3)-127.0.0.1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 52 ms
  2020-07-14 02:46:03.449  INFO 11120 --- [nio-8081-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
  2020-07-14 02:46:03.451  INFO 11120 --- [nio-8081-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 2 ms
  </code></pre>
  <p>As we can see the <code>api-servlet</code> context and the <code>mvc-servlet</code> context are loaded successfully.</p>
  <p>Maybe a conflict with the default <code>dispatcherServlet</code> context but if so I have no idea the way to solve the problem.</p>