Hey!

Spring Boot 4.0.0-SNAPSHOT

Interface WebClient.Builder has method apply(). It would be fine, to see it also for ClientHttpConnectorBuilder ❤️ Current methods starting with prefix with doesn't accept Consumer<ReactorClientHttpConnectorBuilder> as a paremeter.

For global customizers I can use WebClientCustomizer and ClientHttpConnectorBuilderCustomizer but I want apply some specific configuration per given WebClient

class WebClientConfig {

    private final WebClient.Builder webClientBuilder;

    private final ReactorClientHttpConnectorBuilder reactorClientHttpConnectorBuilder;

    private final SpecificWebClientInstanceConfig specificWebClientInstanceConfig;

    WebClientConfig(WebClient.Builder webClientBuilder, ReactorClientHttpConnectorBuilder reactorClientHttpConnectorBuilder, SpecificWebClientInstanceConfig specificWebClientInstanceConfig) {
        this.webClientBuilder = webClientBuilder;
        this.reactorClientHttpConnectorBuilder = reactorClientHttpConnectorBuilder;
        this.specificWebClientInstanceConfig = specificWebClientInstanceConfig;
    }


    public WebClient createWebClient() {
        return this.webClientBuilder
                .apply(this.specificWebClientInstanceConfig.applyWebClientDefaults())
                .clientConnector(
                        // Current way
                        this.specificWebClientInstanceConfig
                                .applyReactorConnectorDefaults(this.reactorClientHttpConnectorBuilder)
                                .build()
                        // Expected way
//                      this.reactorClientHttpConnectorBuilder
//                              .apply(this.specificWebClientInstanceConfig.applyReactorConnectorDefaults())
//                              .build()
                )
                .build();
    }

}

class SpecificWebClientInstanceConfig {

    Consumer<WebClient.Builder> applyWebClientDefaults() {
        return builder -> {
        };
    }

    // current way
    ReactorClientHttpConnectorBuilder applyReactorConnectorDefaults(
            ReactorClientHttpConnectorBuilder reactorClientHttpConnectorBuilder) {
        return reactorClientHttpConnectorBuilder;
    }


    // expected way
    Consumer<ReactorClientHttpConnectorBuilder> applyReactorConnectorDefaults() {
        return builder -> {
        };
    }

}

Please let me know what do you think about this. I can contribute to this 🫡

Comment From: philwebb

Unlike WebClient.Builder the ClientHttpConnectorBuilder implementations are immutable and always return a new instance. So we can't support Consumer<ReactorClientHttpConnectorBuilder>, it would have to be `BinaryOperator.

We can certainly consider adding a method for that, but I'm not sure how useful it would be since it doesn't seem to save a lot typing:

this.connectorBuilder.with(this.connectorConfig::apply).build()

vs:

this.connectorConfig.apply(this.connectorBuilder).build();

Is there a specific reason you prefer the first approach vs the second?

Comment From: mateusz-nalepa

Thx @philwebb for answer!

it would have to be BinaryOperator. sounds probably good. Could you please show example how it could look like?

I would say, that the main reason for: this.connectorBuilder.with(this.connectorConfig::apply).build() is to reduce cognitive load.

Right now, there are two classes needed and there is no option to use them in exactly the same way, even if they are very close to each other.

Also, for me method apply feels like a story, I mean: -> configure webClientBuilder by applying some specific configuration

sounds in my opinion much better than: -> use this specific configuration to apply modification to webClientBuilder

Another reason, in many different projects I will probably see webClientBuilder with many different configuration classes which can have a lot of different names. But webClientBuilder will be probably used among all of them, so in my opinion it's good to see first something, which is common, that something, which is specific.

Yet another reason, I know, it may sounds like very small change, but for example, thanks to Trailing comma it's possible to see pull requests with only one changed line, instead of three lines

Image

Trailing comma

Also, usually we (developers) spend most of the time on reading the code, not writing it :D

So that's why I think, that it would be nice to see some method on ClientHttpConnectorBuilder which is similar to webClientBuilder.apply()

I'm open to your feedback!

Comment From: philwebb

Slight mistake with my earlier comment, I meant UnaryOperator not BinaryOperator.