Using Guava‑Retrying for Flexible Retry Strategies in Java

This article introduces the Guava‑Retrying library for Java, explains how to add its Maven dependency, demonstrates building a Retryer with customizable retry conditions, stop strategies, wait strategies, and listeners, and provides detailed code examples illustrating each component.

Code Ape Tech Column
Code Ape Tech Column
Code Ape Tech Column
Using Guava‑Retrying for Flexible Retry Strategies in Java

In modern micro‑service development, external calls often fail due to time‑outs or rate‑limits, so a reliable retry mechanism is essential. The Guava‑Retrying library, an extension of Google’s Guava, offers a powerful yet easy‑to‑use framework for configuring retry policies.

Maven dependency :

<dependency>
  <groupId>com.github.rholder</groupId>
  <artifactId>guava-retrying</artifactId>
  <version>2.0.0</version>
</dependency>

Basic usage – build a Retryer with RetryerBuilder to set when to retry, stop conditions, wait intervals, and execution time limits:

private int invokeCount = 0;

public int realAction(int num) {
    invokeCount++;
    System.out.println(String.format("当前执行第 %d 次,num:%d", invokeCount, num));
    if (num <= 0) {
        throw new IllegalArgumentException();
    }
    return num;
}

@Test
public void guavaRetryTest001() {
    Retryer<Integer> retryer = RetryerBuilder.<Integer>newBuilder()
        .retryIfRuntimeException()
        .retryIfResult(result -> result % 2 == 0)
        .withStopStrategy(StopStrategies.stopAfterAttempt(3))
        .build();
    try {
        invokeCount = 0;
        retryer.call(() -> realAction(0));
    } catch (Exception e) {
        System.out.println("执行0,异常:" + e.getMessage());
    }
    // similar calls for 1 and 2 omitted for brevity
}

The output shows the retry attempts and the final failure after three tries.

Retry timing (when to retry) – Guava‑Retrying provides methods such as retryIfException(), retryIfRuntimeException(), retryIfException(Predicate), and retryIfExceptionOfType(Class) for exception‑based retries, as well as retryIfResult(Predicate) for result‑based retries.

Stop strategies determine when retries should cease. Examples include:

public interface StopStrategy {
    /** Returns true if the retryer should stop retrying. */
    boolean shouldStop(Attempt failedAttempt);
}

// NeverStopStrategy – never stops
@Override
public boolean shouldStop(Attempt failedAttempt) {
    return false;
}

// StopAfterAttemptStrategy – stops after a fixed number of attempts
private final int maxAttemptNumber;
public StopAfterAttemptStrategy(int maxAttemptNumber) {
    Preconditions.checkArgument(maxAttemptNumber >= 1, "maxAttemptNumber must be >= 1 but is %d", maxAttemptNumber);
    this.maxAttemptNumber = maxAttemptNumber;
}
@Override
public boolean shouldStop(Attempt failedAttempt) {
    return failedAttempt.getAttemptNumber() >= maxAttemptNumber;
}

Wait (interval) strategies control the pause between retries. Common implementations are:

// FixedWaitStrategy – constant interval
private final long sleepTime;
public FixedWaitStrategy(long sleepTime) {
    Preconditions.checkArgument(sleepTime >= 0L, "sleepTime must be >= 0 but is %d", sleepTime);
    this.sleepTime = sleepTime;
}
@Override
public long computeSleepTime(Attempt failedAttempt) {
    return sleepTime;
}

// IncrementingWaitStrategy – linearly increasing interval
private final long initialSleepTime;
private final long increment;
public IncrementingWaitStrategy(long initialSleepTime, long increment) {
    Preconditions.checkArgument(initialSleepTime >= 0L, "initialSleepTime must be >= 0 but is %d", initialSleepTime);
    this.initialSleepTime = initialSleepTime;
    this.increment = increment;
}
@Override
public long computeSleepTime(Attempt failedAttempt) {
    return initialSleepTime + increment * (failedAttempt.getAttemptNumber() - 1);
}

// RandomWaitStrategy – random interval between min and max
private static final Random RANDOM = new Random();
private final long minimum;
private final long maximum;
public RandomWaitStrategy(long minimum, long maximum) {
    Preconditions.checkArgument(minimum >= 0, "minimum must be >= 0 but is %d", minimum);
    Preconditions.checkArgument(maximum > minimum, "maximum must be > minimum");
    this.minimum = minimum;
    this.maximum = maximum;
}
@Override
public long computeSleepTime(Attempt failedAttempt) {
    long t = Math.abs(RANDOM.nextLong()) % (maximum - minimum);
    return t + minimum;
}

Other strategies such as ExponentialWaitStrategy, FibonacciWaitStrategy, and CompositeWaitStrategy combine or modify these behaviours.

Retry listeners allow custom actions (e.g., logging) on each retry attempt:

Retryer<Integer> retryer = RetryerBuilder.<Integer>newBuilder()
    .retryIfException()
    .withRetryListener(new MyRetryListener())
    .withStopStrategy(StopStrategies.stopAfterAttempt(3))
    .build();

private static class MyRetryListener implements RetryListener {
    @Override
    public <V> void onRetry(Attempt<V> attempt) {
        System.out.println("第" + attempt.getAttemptNumber() + "次执行");
    }
}

The core execution loop in Retryer.call() creates an Attempt object, notifies listeners, checks the rejection predicate, applies the stop strategy, computes the wait time via the chosen WaitStrategy, blocks using the selected BlockStrategy, and repeats until success or a stop condition is met.

In summary, Guava‑Retrying combines the Builder pattern with multiple strategy interfaces to provide a highly configurable and extensible retry mechanism that can be easily adapted to various backend scenarios.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaBackend DevelopmentspringRetrystrategyGuava-Retrying
Code Ape Tech Column
Written by

Code Ape Tech Column

Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.