Spring has introduced the new HTTP interface. For exception handling the documentation states to register a response status handler that applies to all responses performed through the client:
WebClient webClient = WebClient.builder()
.defaultStatusHandler(HttpStatusCode::isError, resp -> ...)
.build();
However, it's not clear how to handle retries.
In WebClient you could simple use retryWhen():
public Mono<String> getData(String stockId) {
return webClient.get()
.uri(PATH_BY_ID, stockId)
.retrieve()
.bodyToMono(String.class)
.retryWhen(Retry.backoff(3, Duration.ofSeconds(2)));
}
I'm not sure how to incorporate retries with the Http interfaces.
I figured it out. You need to use an exchange filter. I implemented a similiar solution for a different problem: Adding a retry all requests of WebClient
@Bean
TodoClient todoClient() {
WebClient webClient =
WebClient.builder()
.baseUrl("sampleUrl")
.filter(retryFilter())
.build();
HttpServiceProxyFactory factory =
HttpServiceProxyFactory.builder(WebClientAdapter.forClient(webClient)).build();
return factory.createClient(TodoClient.class);
}
private ExchangeFilterFunction retryFilter() {
return (request, next) ->
next.exchange(request)
.flatMap(clientResponse ->
Mono.just(clientResponse)
.filter(response -> clientResponse.statusCode().isError())
.flatMap(ClientResponse::createException)
.flatMap(Mono::error)
.thenReturn(clientResponse)
)
.retryWhen(
Retry.fixedDelay(3, Duration.ofSeconds(30))
.doAfterRetry(retrySignal -> log.warn("Retrying"))
);
}