Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using multiple dispatcher servlets / web contexts with spring boot

I created a spring boot application with a parent context (services) and child context (spring-webmvc controllers):

@Configuration public class MainApiApplication {      public static void main(String[] args) {         new SpringApplicationBuilder()                 .parent(Services.class)                 .child(ApiOne.class, MainApiApplication.class)                 .run(args);     }      @Bean     public EmbeddedServletContainerFactory servletContainer() {         return new TomcatEmbeddedServletContainerFactory();     }  } 

Now I want to add another client context (and DispatcherServlet) for my ApiTwo.class configuration. I think I have to do two things:

  1. Move the servletContainer (thus the MainApiApplication.class configuration) out of the child context and
  2. add a path mapping /one/ -> ApiOne.class and /two/ ApiTwo.class

What is the spring boot way to do it?

like image 735
Jan Avatar asked Mar 17 '15 10:03

Jan


People also ask

Can we have multiple dispatcher servlet in Spring?

You can have as many DispatcherServlets as you want. Basically what you need to do is duplicate the configuration and give the servlet a different name (else it will overwrite the previous one), and have some separate configuration classes (or xml files) for it.

Can we have more than one dispatcher servlet in web xml?

A web application can define any number of DispatcherServlet instances. Each servlet will operate in its own namespace, loading its own application context with mappings, handlers, etc. Only the root application context as loaded by ContextLoaderListener, if any, will be shared.

Can we have multiple context path in Spring boot?

In order to have multiple context paths, you're limited to deploying the application multiple times with that convenient property set to what you want for each deployment. However, this is resource expensive because you're spinning up two applications for every one application you would normally spin up.

Can Spring have multiple application contexts?

We can have multiple application contexts that share a parent-child relationship. A context hierarchy allows multiple child contexts to share beans which reside in the parent context. Each child context can override configuration inherited from the parent context.


2 Answers

As @josh-ghiloni already said, you need to register a ServletRegistrationBean for every isolated web context you want to create. You need to create an application context from a xml or java config class. You can use @Import and @ComponentScan annotation to add shared services to the parent context. Here is an example:

import org.springframework.boot.SpringApplication; import org.springframework.boot.context.embedded.ServletRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.context.support.XmlWebApplicationContext; import org.springframework.web.servlet.DispatcherServlet;   //@ComponentScan({"..."}) //@Import({}) public class Starter {      public static void main(String[] args) throws Exception {         SpringApplication.run(Starter.class, args);     }      @Bean     public ServletRegistrationBean apiV1() {         DispatcherServlet dispatcherServlet = new DispatcherServlet();          XmlWebApplicationContext applicationContext = new XmlWebApplicationContext();         applicationContext.setConfigLocation("classpath:/META-INF/spring/webmvc-context.xml");         dispatcherServlet.setApplicationContext(applicationContext);          ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(dispatcherServlet, "/api/1/*");         servletRegistrationBean.setName("api-v1");          return servletRegistrationBean;     }      @Bean     public ServletRegistrationBean apiV2() {         DispatcherServlet dispatcherServlet = new DispatcherServlet();          AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();         applicationContext.register(ResourceConfig.class);         dispatcherServlet.setApplicationContext(applicationContext);          ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(dispatcherServlet, "/api/2/*");         servletRegistrationBean.setName("api-v2");         return servletRegistrationBean;     } } 
like image 88
ksokol Avatar answered Sep 20 '22 16:09

ksokol


Create a ServletRegistrationBean that declares the servlet and its mappings. You will probably also want to exclude DispatcherServletAutoConfiguration from the autoconfigurations called, because it will register a DispatcherServlet at / and override yours

EDIT Despite my comment below saying you might not need this, unless you need your APIs running on separate ports (and it doesn't sound like you do), Dave Syer, one of the authors of Spring Boot, answered a very similar question here: Configure multiple servletcontainers/servlets with spring boot

like image 35
Josh Ghiloni Avatar answered Sep 22 '22 16:09

Josh Ghiloni