Why Spring’s Functional Router Fails with /api Prefix and How to Fix It
This article explains a bug in Spring 6.1.11 where adding a servlet path prefix causes functional routing to throw an UnsupportedOperationException, demonstrates the issue with code and screenshots, and provides work‑arounds and the permanent fix introduced in Spring 6.1.12.
Environment : Spring 6.1.11 (used by SpringBoot 3.2.8).
Bug introduction : When using Spring Web MVC’s functional programming model (WebMvc.fn) – an alternative to the annotation‑based @RequestMapping – a specific nested route causes an exception.
1.1 Route interface definition
<code>@Bean
RouterFunction<ServerResponse> userRouter(UserHandler handler) {
return route()
.path("/routers/users", builder -> builder
.GET("/{id}", accept(MediaType.TEXT_HTML), handler::findById))
.build();
}</code>1.2 Route handler
<code>@Component
public class UserHandler {
public ServerResponse findById(ServerRequest request) {
User user = new User(
Long.valueOf(request.pathVariable("id")),
request.param("name").orElse(null)
);
return ServerResponse.ok().body(user);
}
}</code>Testing the request works correctly (see screenshot).
1.3 Bug reproduction
Adding the following servlet path configuration introduces the error:
<code>spring:
mvc:
servlet:
path: /api</code>This configuration prefixes the DispatcherServlet path with /api . After the change, accessing /routers/users/* results in an error (see screenshots).
Explanation : The exception occurs only for nested routes; ordinary routes are unaffected.
2. Submitting an issue to Spring
The author reported the problem to the Spring team, who confirmed it and suggested a temporary workaround by setting the server context path:
<code>server:
servlet:
context-path: /api</code>This workaround resolves the issue.
Permanent fix
The bug was fixed in Spring 6.1.12. Since SpringBoot 3.2.8 bundles Spring 6.1.11, you can either upgrade the Spring framework version in pom.xml :
<code><properties>
<spring-framework.version>6.1.12</spring-framework.version>
</properties></code>or avoid using nested functional routes.
Error cause
In Spring 6.1.11, ServletRequestPathUtils.modifyContextPath throws UnsupportedOperationException when handling nested routes:
<code>public abstract class ServletRequestPathUtils {
private static final class ServletRequestPath implements RequestPath {
// contextPath = /routers/users/6666 (no /api prefix yet)
public RequestPath modifyContextPath(String contextPath) {
// directly throws exception
throw new UnsupportedOperationException();
}
}
}</code>In Spring 6.1.12 the method was corrected to concatenate the configured servlet path prefix:
<code>private static final class ServletRequestPath implements RequestPath {
public RequestPath modifyContextPath(String contextPath) {
// Append /api to the current request path
return new ServletRequestPath(this.pathElements.withContextPath(contextPath));
}
}</code>Thus, upgrading or avoiding nested functional routes resolves the problem.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.