1

I've been learning spring webflux and got stuck into this one.

I've made a request to REST API from Spring app using WebClient. I want to retry the request based on the response. lets say if the response has property status: 'not-ready', then I need to retry the same operation after a second.

I tried the following way, but not sure how to implement it

public Flux<Data> makeHttpRequest(int page) {
        Flux<Data> data = webClient.get()
                .uri("/api/users?page=" + page)
                .retrieve()
                .bodyToFlux(Data.class);
        return data;
}
GET : /api/users returns the folowing response

ex: 1 {
  status: 'ready',
  data: [......]
}

ex: 2 {
  status: 'not-ready',
  data: null
}

Any help would be appreciated.

user3470629
  • 511
  • 1
  • 8
  • 20
  • You need to use `Mono.retryWhen` in combination with `exchange()` (rather than `retrieve`) - see the documentation for an example https://projectreactor.io/docs/core/release/reference/#faq.retryWhen – Boris the Spider Sep 20 '19 at 05:14
  • hi can tell me few things first 1. Rest api you create is always give you response with example is showing you 2. which firsthand are using and what type of call making to get rest end called Like ( Http async or sync) – harkesh kumar Sep 20 '19 at 05:15
  • this might help https://stackoverflow.com/questions/65744150/spring-webclient-how-to-retry-with-delay-based-on-response-header – Mukesh May 25 '21 at 07:57

1 Answers1

1

I think it is fairly easy to implement the desired retry logic. Something along the lines of:

public class SampleRequester {

    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

    private WebClient client;

    public SampleRequester() {
        this.client = WebClient.create();
    }

    public void scheduleRequest(int secondsDelay) {
        scheduler.schedule(this::initiateRequest, secondsDelay, SECONDS);
    }

    private void initiateRequest() {
        Mono<ResponseData> response = client.get()
                .uri("example.com")
                .retrieve()
                .bodyToMono(ResponseData.class);

        response.subscribe(this::handleResponse);
    }

    private void handleResponse(ResponseData body) {
        if("ready".equals(body.getStatus())) {
            System.out.println("No Retry");
            // Do something with the data
        } else {
            System.out.println("Retry after 1 second");
            scheduleRequest(1);
        }
    }
}

I used the following simple model for the response:

public class ResponseData implements Serializable {

    private String status;

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }
}   

Then you would call SampleRequester.scheduleRequest(0) to initiate the first call immediately. Of course you would also need to adapt to avoid hard-coding the request url, extending the ResponseData, make the delay configurable and/or exponential backoff etc.

  • this might help https://stackoverflow.com/questions/65744150/spring-webclient-how-to-retry-with-delay-based-on-response-header – Mukesh May 25 '21 at 07:57