Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How make "fire and forget" request sending in spring webflux webclient?

Consider a code:

private WebClient webClient;

public void some(MyObject myObject) {
    return webClient.post()
            .uri("/log/my-path")
            .body(BodyInserters.fromObject(myObject))
            .retrieve()
            .bodyToMono(Void.class)
            .subscribeOn(Schedulers.single());
}

This code "waits" when response "appears" and then completes. (E.g. retrieve() is called). but how not to wait for response? For example, I make request and return Mono.empty without waiting for response. How to do that?

P.S. A technique when request is sent without wating for response is called "fire and forget".

UPDATED

  1. Any mono functions like then does not work. Because they invocated after bodyToMono which "waits" until http response is comming. E.g. nothing (event async) is called until bodyToMono completes.
  2. "remove" return statment also does not work. May be in some main functions it works but not in Spring application. This does not wok because Mono just created in that case, but nobody run it. Any Mono methods like map, flatMap etc. is just funciton "setting" but not Mono running.
like image 438
Cherry Avatar asked Nov 04 '18 18:11

Cherry


1 Answers

There are several ways to do that. You could do the following:

public void some(MyObject myObject) {
    return webClient.post()
            .uri("/log/my-path")
            .body(BodyInserters.fromObject(myObject))
            .retrieve()
            .bodyToMono(Void.class)
            .subscribe();
}

This has an important problem: even if you're not interested in the response itself, you might want to have specific properties like:

  • Being notified in case of errors and handling those
  • Making sure that, in case of a batch/CLI app, something is holding onto that request and prevents your application from exiting, thinking that everything is done

In that case, you can chain the response with a Mono<Void> type, which is completed as Mono.empty() or an error:

public Mono<Void> some(MyObject myObject) {
    return webClient.post()
            .uri("/log/my-path")
            .body(BodyInserters.fromObject(myObject))
            .retrieve()
            .bodyToMono(Void.class)
            .then();
}

In other parts of your application, you can then chain again with other publishers:

Mono<Void> requestSent = some(myObject);
Mono<Other> other = requestSent.then(otherMono);
like image 73
Brian Clozel Avatar answered Sep 19 '22 16:09

Brian Clozel