I am using WebClient for an API Call in a springboot project. I want to handle retries if the response code is 5xx. When a status code 5xx comes, I want to throw a CustomException. I am handling this exception like below in the method that is calling this API.
@Retryable(
backoff = @Backoff(delayExpression = "${upload.retry.delay:10000}"),
maxAttemptsExpression = "${upload.max.retry.limit:3}",
include = {FileProcessingException.class})
I have a tried a few things, but those don't seem to work.
- don't have any effect on the code. It passes and when I do .block, throws NPE.
void getAuthToken(){
authorizationTokenResponse =
webClient
.post()
.uri(apiUrl + LOGIN)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.bodyValue(gson.toJson(loginRequest))
.retrieve()
.onStatus(HttpStatus::is4xxClientError,
response -> response.bodyToMono(String.class).map(FileProcessingException::new))
.onStatus(HttpStatus::is5xxServerError,
response -> response.bodyToMono(String.class).map(FileProcessingException::new))
.bodyToMono(AuthorizationTokenResponse.class)
.retry(3);
}
- I tried the following : https://stackoverflow.com/questions/58520919/spring-webclient-retry-with-backoff-on-specific-error#:~:text=You%20can%20do%20this%20taking%20the%20following%20approach%3A
But I get the compilation error:
no instance(s) of type variable(s) R exist so that String conforms to Mono<? extends R>
void getAuthToken() {
.exchange().flatMap(responseFromAPI -> {
if(responseFromAPI.statusCode().is5xxServerError() || responseFromAPI.statusCode().is4xxClientError()){
return Mono.error(new FileProcessingException());
} else {
AuthorizationTokenResponse tokenResponse = responseFromAPI.bodyToMono(AuthorizationTokenResponse.class).block();
authToken = tokenResponse.getAuthorizationToken();
authTokenExpDateTime =
LocalDateTime.parse(tokenResponse.getTokenExpirationDateTime(),
DateTimeFormatter.ISO_DATE_TIME);
return authToken;
}
});
}
- This is my original code:
void getAuthToken() {
ResponseSpec clientResponse =
webClient
.post()
.uri(apiUrl + LOGIN)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.bodyValue(gson.toJson(loginRequest))
.retrieve();
}
Code is throwing NPE when doing below:
responseEntity = Objects.requireNonNull(clientResponse.toEntity(AuthorizationTokenResponse.class).block());
I just want to check if the response code is not 200, throw a CustomException, which I can use for retrying.
Thanks!
Edit 1: I didn't mention that I using CompletableFuture to call getAuthToken(). Below is the code:
listOfLineReadFromFile.stream()
.map(
lineReadFromList ->
CompletableFuture.runAsync(() -> handleLine(lineReadFromList), executorService))
.forEach(CompletableFuture::join);
where listOfLineReadFromFile
is the list for which authToken() is required.