We have two classes annotated with @RestController and with the same name in different packages. Since by default the bean name is the class name this generates an issue when booting the application. For this reason, we give a custom name to each class via @RestController's value field. However, it appears that when the bean name starts with a / Spring tries to exposes that name as a servlet path.

Here's an example (I've also attached a .zip with the entire code):

package com.example.demo.namespace1;

@RestController("/potato")
@RequestMapping("/namespace1/demo")
public class DemoController {
    @GetMapping
    public String handler() {
        return "/namespace1/demo";
    }
}
package com.example.demo.namespace2;

@RestController("/tomato")
@RequestMapping("/namespace2/demo")
public class DemoController {
    @GetMapping
    public String handler() {
        return "/namespace2/demo";
    }
}

The following requests result in:

  • GET http://localhost:8080/namespace1/demo -> 200
  • GET http://localhost:8080/namespace2/stuff -> 404
  • GET http://localhost:8080/potato -> 500 Stack trace:
2021-10-07 09:41:20.541 ERROR 2749 --- [nio-8080-exec-3] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [No adapter for handler [com.example.demo.namespace1.DemoController@7e2e9e87]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler] with root cause

javax.servlet.ServletException: No adapter for handler [com.example.demo.namespace1.DemoController@7e2e9e87]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler
    at org.springframework.web.servlet.DispatcherServlet.getHandlerAdapter(DispatcherServlet.java:1302) ~[spring-webmvc-5.3.10.jar:5.3.10]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1050) ~[spring-webmvc-5.3.10.jar:5.3.10]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963) ~[spring-webmvc-5.3.10.jar:5.3.10]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.10.jar:5.3.10]
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.3.10.jar:5.3.10]

It appears that when the bean name starts with a / that name tries to be exposed as a servlet path but since there's no handler for that path the request results in an error. This looks suspicious as the behaviour of the application is different depending on the names of the beans.

I was trying to understand if this behaviour is expected but haven't found any mention to this in the documentation so far.

(This might be a Spring issue and not Spring Boot so apologies if opening in the wrong tracker.)

demo.zip

Comment From: sbrannen

I was trying to understand if this behaviour is expected but haven't found any mention to this in the documentation so far.

This is the expected behavior.

Whenever you use @EnableWebMvc, that automatically imports DelegatingWebMvcConfiguration which extends WebMvcConfigurationSupport, and WebMvcConfigurationSupport automatically registers a BeanNameUrlHandlerMapping.

The BeanNameUrlHandlerMapping is what is mapping http://localhost:8080/potato to your @RestController("/potato") annotated controller.

In light of that, I am closing this issue.

Comment From: joca-bt

Is there a quick way of disabling BeanNameUrlHandlerMapping?

Comment From: sbrannen

You should be able to override org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport.beanNameHandlerMapping(FormattingConversionService, ResourceUrlProvider) so that it simply returns null.

Give that a try and let us know if it works for you.