It seems the propertyserver.servlet-path
in Spring Boot 1.5 has then been changed to server.servlet.path
in Spring Boot 2.0 and spring.mvc.servlet.path
in Spring Boot 2.1 (https://github.com/spring-projects/spring-boot/issues/12971)
With this last step, it seems it is not legal anymore to use a '*' in the path, in the form of:
spring.mvc.servlet.path=/*
See: https://github.com/spring-projects/spring-boot/issues/13292 I might be the one complaining about it.
/
and /*
seems legit value as path, and in some cases, one may prefer to use /*
for any reason (e.g. https://bluxte.net/musings/2006/03/29/servletpath-and-pathinfo-servlet-api-weirdness/)
In my case, I consider a project relying on a commercial library (i.e. no way to change their implementation), itself relying on CXF. For some API pathes, a ServletWrappingController redirects the call to some CXF Servlet (version 3.2.4), with a stack looking like:
Daemon Thread [http-nio-8080-exec-8] (Suspended (breakpoint at line 166 in ServletController))
owns: NioEndpoint$NioSocketWrapper (id=201)
ServletController.invoke(HttpServletRequest, HttpServletResponse, boolean) line: 166
ServletController.invoke(HttpServletRequest, HttpServletResponse) line: 160
CXFServlet(CXFNonSpringServlet).invoke(HttpServletRequest, HttpServletResponse) line: 216
CXFServlet(AbstractHTTPServlet).handleRequest(HttpServletRequest, HttpServletResponse) line: 301
CXFServlet(AbstractHTTPServlet).doGet(HttpServletRequest, HttpServletResponse) line: 225
CXFServlet(HttpServlet).service(HttpServletRequest, HttpServletResponse) line: 634
CXFServlet(AbstractHTTPServlet).service(ServletRequest, ServletResponse) line: 276
XXXServletWrappingController(ServletWrappingController).handleRequestInternal(HttpServletRequest, HttpServletResponse) line: 165
XXXServletWrappingController(AbstractController).handleRequest(HttpServletRequest, HttpServletResponse) line: 177
SimpleControllerHandlerAdapter.handle(HttpServletRequest, HttpServletResponse, Object) line: 52
DispatcherServlet.doDispatch(HttpServletRequest, HttpServletResponse) line: 1038
DispatcherServlet.doService(HttpServletRequest, HttpServletResponse) line: 942
DispatcherServlet(FrameworkServlet).processRequest(HttpServletRequest, HttpServletResponse) line: 998
DispatcherServlet(FrameworkServlet).doGet(HttpServletRequest, HttpServletResponse) line: 890
DispatcherServlet(HttpServlet).service(HttpServletRequest, HttpServletResponse) line: 634
DispatcherServlet(FrameworkServlet).service(HttpServletRequest, HttpServletResponse) line: 875
DispatcherServlet(HttpServlet).service(ServletRequest, ServletResponse) line: 741
At this point:
String pathInfo = request.getPathInfo() == null ? "" : request.getPathInfo();
is always null. It appears the whole path is in ther RequestPath of the undelrying HttpServletRequest, but the pathInfo remained empty.
This is workarounded by having spring.mvc.servlet.path=/*
, in which case .getPathInfo returns the expected value (the whole path).
I'm not a pro with servlets. It might be an issue with CXF which might have been responsible for having look at request.getRequestURI()
. Still, the issue was workarounded with previous SpringBoot by using server.servlet.path=/*
Comment From: philwebb
That's an interesting problem but it does feel like an issue in CXF or the commercial library. I think that this line might also need to consider getServletPath()
.
I'm not too keen to relax those rules again but it should be possible for you to create your own dispatcherServletRegistration
@Bean
in code and provide the mapping you need.
Comment From: blacelle
I agree about the probable root-cause.
I tried the following without success:
// Primary over the one in dispatcherServletAutoConfiguration
@Primary
@Bean(name = DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME)
@ConditionalOnBean(value = DispatcherServlet.class,
name = DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
public DispatcherServletRegistrationBean apexDispatcherServletRegistration(DispatcherServlet dispatcherServlet,
WebMvcProperties webMvcProperties,
ObjectProvider<MultipartConfigElement> multipartConfigProvider) {
MultipartConfigElement multipartConfig = multipartConfigProvider.getIfAvailable();
String servletPath = webMvcProperties.getServlet().getPath();
if ("/wildcard".equals(servletPath)) {
servletPath = "/*";
}
DispatcherServletRegistrationBean registration =
new DispatcherServletRegistrationBean(dispatcherServlet, servletPath);
registration.setName(DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_BEAN_NAME);
registration.setLoadOnStartup(webMvcProperties.getServlet().getLoadOnStartup());
if (multipartConfig != null) {
registration.setMultipartConfig(multipartConfig);
}
return registration;
}
I guess that, as the bean name is forced to DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME
, trying to change the methodName
and adding @Primary
is non-sense. Am I required to deactivate manually the whole DispatcherServletAutoConfiguration
?
Comment From: philwebb
Try the following:
@Bean
public DispatcherServletRegistrationBean dispatcherServletRegistration(
DispatcherServlet dispatcherServlet,
ObjectProvider<MultipartConfigElement> multipartConfig) {
DispatcherServletRegistrationBean registration = new DispatcherServletRegistrationBean(
dispatcherServlet, "/test/*");
registration.setName("dispatcherServlet");
registration.setLoadOnStartup(-1);
multipartConfig.ifAvailable(registration::setMultipartConfig);
return registration;
}
Comment From: philwebb
Given that the problem is not in Spring Boot itself, and there is a work-around, we'd prefer to keep the stricter rules around spring.mvc.servlet.path
.
Please let us know if you can't get the manual DispatcherServletRegistrationBean
registration to work.
Comment From: jonas-gbl
Thank you both, I had the exact same issue (AP?)
Comment From: blacelle
@jonas-gbl Yes AP. Feel free to contact me privately if you have more questions/issues regarding AP
Comment From: karthickrc
@blacelle I am also having same issue now. how did you resolve it?