Use ExtendedServletRequestDataBinder/ExtendedWebExchangeDataBinder for functional request binding
Functional requests gained bind() method as part of #25943
However, it is not possible to obtain a path parameter using bind() method.
Given the router example
import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Component; import org.springframework.web.reactive.function.server.RouterFunction; import org.springframework.web.reactive.function.server.RouterFunctions; import org.springframework.web.reactive.function.server.ServerRequest; import org.springframework.web.reactive.function.server.ServerResponse; import reactor.core.publisher.Mono; @Slf4j @Component public class MyRouter { @Bean public RouterFunction<ServerResponse> myRouter() { return RouterFunctions.route() .GET("/request/{var}", this::handleGet) .build(); } private Mono<ServerResponse> handleGet(ServerRequest request) { return request.bind(Variables.class).flatMap(variables -> Mono.empty()); } @Data static class Variables { private String var; } }
It is not possible to obtain the path parameter variable and bind it this way.
However, if I use the ExtendedWebExchangeDataBinder, it works
import static org.springframework.validation.DataBinder.DEFAULT_OBJECT_NAME; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Bean; import org.springframework.core.ResolvableType; import org.springframework.stereotype.Component; import org.springframework.web.reactive.function.server.RouterFunction; import org.springframework.web.reactive.function.server.RouterFunctions; import org.springframework.web.reactive.function.server.ServerRequest; import org.springframework.web.reactive.function.server.ServerResponse; import org.springframework.web.reactive.result.method.annotation.ExtendedWebExchangeDataBinder; import reactor.core.publisher.Mono; @Slf4j @Component public class MyRouter { @Bean public RouterFunction<ServerResponse> myRouter() { return RouterFunctions.route() .GET("/request/{var}", this::handleGet) .build(); } private Mono<ServerResponse> handleGet(ServerRequest request) { var binder = new ExtendedWebExchangeDataBinder(null, DEFAULT_OBJECT_NAME); binder.setTargetType(ResolvableType.forClass(Variables.class)); binder.setRequiredFields("var"); binder.setAllowedFields("var"); return binder.construct(request.exchange()) .then(binder.bind(request.exchange())) .then( Mono.defer( () -> { var result = binder.getBindingResult(); var params = (Variables) result.getTarget(); return Mono.empty(); })); } @Data static class Variables { private String var; } }
Would you consider supporting the mentioned use-case so we can use path parameters for binding without the boilerplate? Thanks in advance.