Affects: v5.3.1
cannot resolve ServerRequest::pathVariable
in nested RequestPredicate
.
example using Spring Initializer created Project using Spring Boot 2.4.0
package com.example.demo
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.web.servlet.function.ServerRequest
import org.springframework.web.servlet.function.ServerResponse
import org.springframework.web.servlet.function.router
@SpringBootApplication
class DemoApplication
fun main(args: Array<String>) {
runApplication<DemoApplication>(*args)
}
@Configuration
class DemoRouter {
@Bean
fun route() = router {
val handle: (ServerRequest) -> ServerResponse = {
ServerResponse.ok().body(mapOf("id" to it.pathVariable("id")))
}
GET("/person1/{id}", {
true
}, handle)
GET("/person2/{id}", {
it.pathVariable("id")
true
}, handle)
"person3".nest {
GET("/{id}", {
true
}, handle)
}
"person4".nest {
GET("/{id}", {
it.pathVariable("id")
true
}, handle)
}
}
}
only nest and access to pathVariable in RequestPredicate
occurs error.
GET http://localhost:8080/person4/1
HTTP/1.1 500
Content-Type: application/json
Transfer-Encoding: chunked
Date: Fri, 27 Nov 2020 11:33:12 GMT
Connection: close
{
"timestamp": "2020-11-27T11:33:12.870+00:00",
"status": 500,
"error": "Internal Server Error",
"message": "",
"path": "/person4/1"
}
Response code: 500; Time: 155ms; Content length: 123 bytes
java.lang.IllegalArgumentException: No path variable with name "id" available
at org.springframework.web.servlet.function.ServerRequest.pathVariable(ServerRequest.java:225) ~[spring-webmvc-5.3.1.jar:5.3.1]
at org.springframework.web.servlet.function.RequestPredicates$SubPathServerRequestWrapper.pathVariable(RequestPredicates.java:1045) ~[spring-webmvc-5.3.1.jar:5.3.1]
at com.example.demo.DemoRouter$route$1$4$1.test(DemoApplication.kt:40) ~[main/:na]
at org.springframework.web.servlet.function.RequestPredicates$AndRequestPredicate.test(RequestPredicates.java:773) ~[spring-webmvc-5.3.1.jar:5.3.1]
at org.springframework.web.servlet.function.RouterFunctions$DefaultRouterFunction.route(RouterFunctions.java:993) ~[spring-webmvc-5.3.1.jar:5.3.1]
at org.springframework.web.servlet.function.RouterFunctionBuilder$BuiltRouterFunction.route(RouterFunctionBuilder.java:392) ~[spring-webmvc-5.3.1.jar:5.3.1]
at org.springframework.web.servlet.function.RouterFunctions$DefaultNestedRouterFunction.lambda$route$0(RouterFunctions.java:1036) ~[spring-webmvc-5.3.1.jar:5.3.1]
at java.base/java.util.Optional.map(Optional.java:265) ~[na:na]
at org.springframework.web.servlet.function.RouterFunctions$DefaultNestedRouterFunction.route(RouterFunctions.java:1028) ~[spring-webmvc-5.3.1.jar:5.3.1]
at org.springframework.web.servlet.function.RouterFunctionBuilder$BuiltRouterFunction.route(RouterFunctionBuilder.java:392) ~[spring-webmvc-5.3.1.jar:5.3.1]
at org.springframework.web.servlet.function.support.RouterFunctionMapping.getHandlerInternal(RouterFunctionMapping.java:193) ~[spring-webmvc-5.3.1.jar:5.3.1]
at org.springframework.web.servlet.handler.AbstractHandlerMapping.getHandler(AbstractHandlerMapping.java:491) ~[spring-webmvc-5.3.1.jar:5.3.1]
at org.springframework.web.servlet.DispatcherServlet.getHandler(DispatcherServlet.java:1255) ~[spring-webmvc-5.3.1.jar:5.3.1]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1037) ~[spring-webmvc-5.3.1.jar:5.3.1]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:961) ~[spring-webmvc-5.3.1.jar:5.3.1]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.1.jar:5.3.1]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.3.1.jar:5.3.1]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:626) ~[tomcat-embed-core-9.0.39.jar:4.0.FR]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.1.jar:5.3.1]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) ~[tomcat-embed-core-9.0.39.jar:4.0.FR]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.39.jar:9.0.39]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.1.jar:5.3.1]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.1.jar:5.3.1]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.1.jar:5.3.1]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.1.jar:5.3.1]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.1.jar:5.3.1]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.1.jar:5.3.1]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]
If change the Spring Boot version to 2.3.6.RELEASE, that is Spring WebMVC 5.2.11RELEASE, is works.
It seems to be affected from following commit. https://github.com/spring-projects/spring-framework/commit/54e6103defb99c067f3f4d5a6054aa24a29a379e#diff-cc2b40f2447feaaec96bd736d40378d2883c72eab4791c873d7244a135fbe1bdR998-R1007
the commit to use request.attribute
in SubPathServerRequestWrapper
, but the previous commit will use attribute
in SubPathServerRequestWrapper
.