Skip to content

Consider using ExtendedWebExchangeDataBinder for functional request binding #35800

@ZIRAKrezovic

Description

@ZIRAKrezovic

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions