Reputation: 86687
I'm creating ExchangeFilterFunction
for extended logging during WebClient
requests.
Question: is there any difference if I execute the logging inside the .doOnNext()
function in the following example? Or are they equal in processing?
ExchangeFilterFunction.ofRequestProcessor(clientRequest -> {
LOGGER.info("Request url=" + clientResponse.url() + ", method=" + clientResponse.method());
return Mono.just(clientRequest);
});
ExchangeFilterFunction.ofRequestProcessor(clientRequest -> {
return Mono.just(clientRequest).doOnNext(clientResponse2 -> {
LOGGER.info("Request url=" + clientResponse2.url() + ", method=" + clientResponse2.method());
});
});
Is there any advantage for one over the other?
Upvotes: 2
Views: 2443
Reputation: 11551
I just loath any artificial introduction of Mono.just
or similar into your flow. I suppose that .doOnNext
is one extra step but I cannot imagine it makes any difference whatsoever. Better to avoid breaking the flow up. I think that would be your worst performance penalty.
Note: This will log when WebClient
is invoked, as noted below, and generally looks a little uglier than using the convenience methods, but it avoids using Mono.just
.
@Override
public void run(ApplicationArguments args) throws Exception {
WebClient webClient = WebClient.builder()
.baseUrl("http://localhost:8080/")
.filter(eff)
.build();
webClient.get().retrieve().bodyToMono(String.class).subscribe(System.out::println);
}
ExchangeFilterFunction eff = (cr,ef)->{
System.out.println("method: " + cr.method());
return ef.exchange(cr)
.map(cresp->{
System.out.println(cresp.rawStatusCode());
return cresp;
});
};
Upvotes: 2
Reputation: 1386
In this particular case the webclient will invoke the filter correctly. However, be careful about this in general.
In the first case the logging will happen when the method is invoked. It could actually be incorrect if the caller never subscribes to the returned publisher. The publisher could also be called many times like in the case of a retry or repeat, etc. and that will be wrong too.
In the second case it will be called every time it is subscribed to.
public class Foo {
static Mono<String> echo(String message) {
System.out.println("echo called with " + message);
return Mono.just(message);
}
static Mono<String> rxEcho(String message) {
return Mono.just(message).doOnNext(msg -> System.out.println("rxEcho was called with " + msg));
}
public static void main(String[] args) {
//logged, even though never actually called
echo("no sub");
//only logs 1 time
echo("retry")
.repeat(3)
.blockLast();
System.out.println("---------------");
//never subbed, never logged
rxEcho("no sub");
//all 4 calls are logged
rxEcho("retry")
.repeat(3)
.blockLast();
}
}
Also note you shouldn't call any flavor of block() in real code, I didn't want to confuse the example with StepVerifier.
Upvotes: 0