javaspringspring-webfluxspring-webclient

on error do another call and retry in webflux


I'd like to do the following using the WebClient from spring webflux:

I've got this far:

webclient.get()
  .uri("/endpoint1")
  .retrieve()
  .bodyToFlux(MyBody.class)
  .retry(error -> {
     if (error == expectedError) {
       webclient.get()
         .uri("/endpoint2")
         .retrieve().block();
       return true;
     } else {
       false;
     });

I cannot block when requesting endpoint2 since I would get the following error: block()/blockFirst()/blockLast() are blocking, which is not supported in thread (I wouldn't like to block either).

Maybe I should use retryWhen but I'm not really sure how to use it.


Solution

  • The only way I made this work was with retryWhen I could not use reactor.retry.Retry#doOnRetry because it only accepts a Consumer not a Mono or Flux or Publisher.

    The snippet is as follows:

    webclient.get()
      .uri("/endpoint1")
      .retrieve()
      .bodyToFlux(MyBody.class)
      .retryWhen(errorCurrentAttempt -> errorCurrentAttempt
                    .flatMap(currentError -> Mono.subscriberContext().map(ctx -> Tuples.of(currentError, ctx)))
                    .flatMap(tp -> {
                        Context ctx = tp.getT2();
                        Throwable error = tp.getT1();
                        int maxAttempts = 3;
                        Integer rl = ctx.getOrDefault("retriesLeft", maxAttempts);
                        if (rl != null && rl > 0 && error == myExpectedError) {
                            // Call endpoint and retry
                            return webclient.get()
                                    .uri("/endpoint2")
                                    .retrieve()
                                    .thenReturn(ctx.put("retriesLeft", rl - 1));
                        } else {
                            // Finish retries
                            return Mono.<Object>error(error);
                        }
                    }));