Using the fault tolerance features

The REST client includes a set of fault tolerance features that can be applied to a REST call.

How to use the retry

This is used to retry executing a piece of code multiple times if a particular type of exception is thrown. Configure the retry properties using the following settings:

Table 1. Configurations
Setup property Default value Description
maxAttempts 3 The maximum number of attempts before failing
exponentialBackoff None An exponential backoff function to modify the waiting interval after each failure; If not specified, the intervalFunction is used.
intervalFunction Always returns 500ms A function to modify the waiting interval after a failure
retryOnResultPredicate Always false for any result value A predicate determining if a result has to be retried; It must return true, if the result has to be retried, otherwise it must return false.
retryOnExceptionPredicate Always true for any Throwable A predicate determining if an exception has to be retried; It must return true, if the exception has to be retried, otherwise it must return false.

The following example shows how to create the configuration:

Config config = Config.builder()
  .eventHandler(RetrySetup.builder()
    .retryOnResultPredicate(Objects::nonNull)
    .retryOnExceptionPredicate(e -> e instanceof IOException)
    .maxAttempts(7)
    .build();

To specify multiple retry attempts, wrap the retry within another retry, as shown in the following example. This results in executing the throw statement 10 times:

Config config = Config.builder()
  .eventHandler(RetrySetup.builder().maxAttempts(5).build())
  .eventHandler(RetrySetup.builder().maxAttempts(2).build());
  .build();  

How to use CircuitBreaker

You invoke circuit breaker when API calls failed or appeared to be slow. The circuit breaker starts short-circuiting API calls when a failure rate or slow call rate threshold is reached. A circuit breaker instance is used by multiple REST calls to determine the state of the circuit breaker. An instance is uniquely identifiable by its name within a JVM.

Table 2. States
State Description
CLOSED The starting state for circuit breaker, failure rate or slow call rate threshold is calculated.
OPEN Circuit breaker transition to this state once the failure rate or the slow call rate threshold is reached. No API calls are executed. Transition to HALF-OPEN state once wait interval has elapsed.
HALF-OPEN Permits a configurable number of calls to see if the backend is still unavailable or has become available again. Once wait interval has elapsed, it transitions to CLOSED state when failure rate or slow call rate is below threshold. Otherwise, it transitions to OPEN state.
Table 3. Configuration
Setup property Default value Description
failureRateThreshold 50 Configures the failure rate threshold in percentage.
slowCallRateThreshold 100 Configures the slow call rate threshold in percentage.
slowCallDurationThreshold 60,000 ms Configures the duration threshold above which calls are considered as slow and increase the rate of slow calls.
permittedNumberOfCallsInHalfOpenState 10 Configures the number of permitted calls when the CircuitBreaker is half open.
slidingWindowType COUNT_BASED Configures the type of the sliding window which is used to record the outcome of calls when the CircuitBreaker is closed.
slidingWindowSize 100 Configures the size of the sliding window which is used to record the outcome of calls.
minimumNumberOfCalls 100 Configures the minimum number of calls which are required (per sliding window period) before the CircuitBreaker can calculate the error rate or slow call rate.
automaticTransitionFromOpenToHalfOpenEnabled false If set to true it means that the CircuitBreaker automatically transitions from open to half-open state and no call is needed to trigger the transition.
waitIntervalFunctionInOpenState Always returns 500ms A function to modify the waiting interval in open state (when circuit breaker short-circuiting the calls).
writableStackTraceEnabled true Enables writable stack traces. Set to false to reduce log spam when the circuit breaker is open as the cause of the exceptions is already known.
recordException Always false for any exceptions A predicate determining if an exception has to be recorded; It must return true, if the exception has to be recorded, otherwise it must return false.

Define circuit breaker with default name and configurations

Config config = Config.builder()
  .eventHandler(CircuitBreakerSetup.builder().build());  // default name is GW_CIRCUITBREAKER
  .build();

Define circuit breaker with custom name and configurations

Config config = Config.builder()
  .eventHandler(CircuitBreakerSetup.builder()
    .name("customeCircuitBreakerName")
    .failureRateThreshold(50)
    .slowCallRateThreshold(100)
    .slowCallDurationThreshold(Duration.ofMillis(60000))
    .permittedNumberOfCallsInHalfOpenState(10)
    .slidingWindowType(CircuitBreakerSetup.SlidingWindowType.COUNT_BASED)
    .slidingWindowSize(100)
    .minimumNumberOfCalls(100)
    .waitIntervalFunctionInOpenState(x -> 500L)
    .automaticTransitionFromOpenToHalfOpenEnabled(false)
    .recordException(e -> e instanceof IOException)
    .writableStackTraceEnabled(true)
    .build())
  .build();

How to use fallback

The following example demonstrates how to use fallback to recover from an exception by returning a specific value:

Config config = Config.builder()
  .eventHandler(FallbackSetup.builder()
    .exceptionType(IOException.class)
    .exceptionHandler(e -> "fallback") // This results in returning the String "fallback".
    .build();

How to use timeout

The following example demonstrates how to set a timeout for a specified piece of code to execute:

Config config = Config.builder()
  .timeout(TimeoutSetup.builder()
    .connectTimeoutMillis(1000)
    .readTimeoutMillis(500)
    .build())
.build();