Implement Retry mechanism within Java 8 Streams and Spring WebFlux Reactive code

Viewed 12

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 -> {

Or should this be done from the .onErrorResume() method chain?

0 Answers
Related