Am using Java 8 and Spring WebFlux to call an external REST based server which also has a backup server.
Currently, if there's a failure when calling the server, it hits the backup server with no retry mechanism:
public class ServiceImpl {
@Autowired
MyRestClient myRestClient;
@Autowired
MyRestClient myRestClientBackup;
public Mono<ResponseOutput> getResponseOutput(ResponseInput responseInput) {
return Mono.just(responseInput)
.flatMap(input -> {
Mono<ResponseOutput> mono = myRestClient.post(input)
.doOnSuccess(responseOutput -> {
log.info("Successfully got responseOutput={}", responseOutput);
});
return mono;
})
.onErrorResume(e -> {
log.warn("Call to server failed, falling back to backup server...");
Mono<ResponseOutput> mono = myRestClientBackup.post(responseInput)
.doOnSuccess(responseOutput ->
log.info("Successfully got backup responseOutput={}", responseOutput));
return mono;
});
}
}
Am trying to implement a retry mechanism where upon setting a numRetries
property in application.yml
set to a specific number, this should happen:
e.g. if the numRetries = 2
Use MyRestClient
to hit the original server twice (since numRetries = 2
) and if that fails to hit the backup server.
This has the numRetries
configuration property set to a static value:
application.yml
:
client:
numRetries: 2;
Class that loads config properties from application.yml
file:
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
@Configuration
public ClientConfig {
@Value("${client.numRetries:0}")
private int numRetries;
// Getters and setters omitted for brevity
}
ClientConfig
is used by MyRestClient
:
public class MyRestClient {
@Autowired
ClientConfig config;
// Getters and setters omitted for brevity
}
Upon obtaining the value for the numRetries
from MyRestClient
how can I change the original implementation inside ServiceImpl.getResponseOutput()
to use numRetries
to hit the original server before calling the backup server? As you can see that this is all originally done using Java 8 lambda and streams...
Found this annotation @Retryable(value = RestClientException.class)
but don't know how to specify the else if numRetries is used to call the backup server
(pseudocode)?
Is there a lambda function to denote the numRetries
to use within the:
return Mono.just(responseInput)
.flatMap(input -> {
How to do use the Mono.retry()
operator?
Also, the version of reactor
in this code seems to have deprecated the Mono.retry().retryBackOff()
method?
How could I use the value referencing numRetries
(which would be an int
) to dictate to keep retrying (upon failure) and then when numRetries
is exceeded up .onErrorResume()
to call the other backup server?
CodePudding user response:
Use retry(int)
operator from Mono
as below:
Mono.just(responseInput)
.flatMap(input -> myRestClient.post(input)
.retry(getNumRetries()) // this is the important part
.doOnSuccess(responseOutput -> log.info("Successfully got responseOutput={}", responseOutput)))
.onErrorResume(e -> {
log.warn("Call to server failed, falling back to backup server...");
return myRestClientBackup.post(responseInput)
.doOnSuccess(responseOutput -> log.info("Successfully got backup responseOutput={}", responseOutput));
});