The retry-logic is implemented in WebClientConfig.ExchangeFilterFunction. I would like to implement similar with repeatWhenEmpty operator.
Uses:
- Java 1.8
- Spring Boot Version 2.1X
- Project Reactor Addons 3.1.6
Configuration:
@Slf4j
@Configuration
public class WebClientConfig {
private static final String host = "https://google.com"; //test host
@Bean
public WebClient retryingClient(WebClient.Builder builder) {
return builder
.baseUrl(host)
.filter(retryFilter())
.build();
}
private ExchangeFilterFunction retryFilter() {
AtomicInteger counter = new AtomicCounter();
return ((request, next) ->
next.exchange(request)
.log()
.doOnNext(clientResponse -> {
log.info(Request: {} {}", request.method(), request.url());
HttpStatus status = clientResponse.statusCode();
if (status == HttpStatus.ACCEPTED) { //retry if the client returns 202
counter.incrementAndGet();
log.info("Retrying : {}", counter.get());
throw new RetryException("Retrying - " + counter.get());
} else if (status.isError()) {
log.info("Error, status code : {}", clientResponse.statusCode);
throw new RuntimeException("Status code : " + clientResponse.statusCode);
}
}).retryWhen(Retry.anyOf(RetryException.class)
.exponentialBackoff(Duration.ofMillis(100), Duration.ofMillis(500))
.retryMax(4));
}
}
This is the service that uses the webClient configured above.
@Service
@Slf4j
public class ExternalCallService {
private final WebClient webClient;
private static final String path = "/flights"; //test url
public ExternalCallService(@Qualifier("retryingClient") WebClient webClient) {
this.webClient = webClient;
}
public Flux<String> fetchFlights(String query) {
return webClient
.get()
.uri(uri -> uri.path(path).queryParam("filter", query).build())
.exchange()
.flatMap(response -> response.bodyToFlux(String.class));
}
}
Runtime exception to help trigger retry
public class RetryException extends RuntimeException {
public RetryException(String msg) {
super(msg);
}
}
Note: I am mostly typing this code in here, please excuse my typo or missing semicolon (if any). I will try to add more details if needed.