Search code examples
javareactive-programmingspring-webfluxproject-reactorspring-boot-actuator

Is there any benefit to add doOnSuccess( ) inside of mono.compose( ) vs simple mono.doOnSuccess( )


Looked into the Spring Actuator MetricsWebFilter

And saw this code:

@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
    return chain.filter(exchange).compose((call) -> filter(exchange, call));
}

private Publisher<Void> filter(ServerWebExchange exchange, Mono<Void> call) {
    long start = System.nanoTime();
    ServerHttpResponse response = exchange.getResponse();
    return call.doOnSuccess((done) -> success(exchange, start))
    ... more code ...
}

Would be there any difference without the compose() mapping?

@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
    return chain.filter(exchange).doOnSuccess( ... ) ... more code...
}

My clues were that compose() is executed once per each subscriber compared to transform(). doOnSuccess() however is also executed once per subscriber.

Is it just for convenience, to use a filter(...) function instead of the inline code?


Solution

  • This has several small benefits in terms of readability:

    • the code is better encapsulated in the filter method
    • the invocation is more readable (reads as transformations occurs). compare to calling the method classically: return filter(exchange, chain.filter(exchange)).

    But in my opinion the more important bit is that compose is Subscriber-specific. As a consequence, the filter(exchange, call) will be invoked on every subscription. And thus the timing code at the beginning will be relevant ;)