user3470629
user3470629

Reputation: 531

how to retry Spring WebClient to retry the operation based on the response?

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.

Upvotes: 1

Views: 4183

Answers (1)

Rumen Kyusakov
Rumen Kyusakov

Reputation: 161

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.

Upvotes: 1

Related Questions