14

I have a following project structure

-Project
 |-config
 |  |-modules
 |     |-admin
 |     |-web
 |- platform 

Platform is the project that contains the spring-boot start class, Platform has a dependency on config and config had dependencies on everything in the directory modules Platform is also the module that gets started with the mvn spring-boot:run command.

The thing I am trying to accomplish is that the modules admin and web (both web apps) have their own mapping like

  • /admin
  • /web

The following code represents an controller in the admin module, the web module also contains a similar controller (thats the point)

@Controller
public class AdminController {

    @RequestMapping("/")
    public String adminController() {
       return "admin";
    }
}

Here some code for the configuration of the admin module

@Configuration
public class Config implements EmbeddedServletContainerCustomizer {

@Autowired
protected WebApplicationContext webApplicationContext;

@Autowired
protected ServerProperties server;

@Autowired(required = false)
protected MultipartConfigElement multipartConfig;

protected DispatcherServlet createDispatcherServlet() {

    AnnotationConfigEmbeddedWebApplicationContext webContext = new AnnotationConfigEmbeddedWebApplicationContext();
    webContext.setParent(webApplicationContext);
    webContext.scan("some.base.package");
    return new DispatcherServlet(webContext);
}

protected ServletRegistrationBean createModuleDispatcher(DispatcherServlet apiModuleDispatcherServlet) {
    ServletRegistrationBean registration =
            new ServletRegistrationBean(apiModuleDispatcherServlet,
                    "/admin");

    registration.setName("admin");
    registration.setMultipartConfig(this.multipartConfig);

    return registration;
}


@Bean(name = "adminsServletRegistrationBean")
public ServletRegistrationBean apiModuleADispatcherServletRegistration() {
    return createModuleDispatcher(createDispatcherServlet());
}

public void customize(ConfigurableEmbeddedServletContainer container) {
    container.setContextPath("/admin");
}
}

Something similar goes for the web module

I have tried the implement the some of the given answers.

  1. Using multiple dispatcher servlets / web contexts with spring boot
  2. Spring Boot (JAR) with multiple dispatcher servlets for different REST APIs with Spring Data REST
  3. And lots of googling

When I let the component scan, scan both modules (removing the ComponentScan filter)

I get an a Ambiguous mapping found exception, saying that both controller methods dispatch to the same path "/"

But when disabling the component scan on one of the modules, then indeed the admin modules get mapped to /admin.

when I disable both controllers, I see that the /web and /admin dispatchServlets get mapped.

So I understand the exception but I dont understand how to resolve this. For me its a must that I can do this per module and I dont want to map it using

@RequestMapping("/admin")

on the controller class

I also tried specifying the contextPath and servletPath in the application.properties

So my question is: what would be the best approach to reach my goal, or am I trying to use spring-boot for something it was not ment for.

Edit A Proof of concept would be nice

Community
  • 1
  • 1
Maikel Bollemeijer
  • 6,545
  • 5
  • 25
  • 48

2 Answers2

4

So I found the solution. You can take a look here at this link

You`ll have to register the dispatcher servlets in the main application and dont use the @SpringBootApplication annotation.

For a complete example just checkout the project and check the code

EDIT: later this week ill provide a detailed answer

Maikel Bollemeijer
  • 6,545
  • 5
  • 25
  • 48
0

What you should do is that put your AdminController and WebController in separate packages.

some.base.admin.package
some.base.web.package 

And in the corresponding configurations scan only your required package to register the DispatcherServlet

Admin Config

webContext.scan("some.base.admin.package");

Web Config

webContext.scan("some.base.web.package");

This way in the corresponding WebApplicationContext for each DispatcherServlet only one mapping will be available for "/"

shazin
  • 21,379
  • 3
  • 54
  • 71