Mastering Retry Logic in Spring and Guava: A Practical Guide

This article explains how to implement robust retry mechanisms in Java applications using Spring‑Retry and Guava‑Retry, covering dependency setup, template configuration, annotation usage, various retry and back‑off policies, and practical code examples with detailed explanations.

Programmer DD
Programmer DD
Programmer DD
Mastering Retry Logic in Spring and Guava: A Practical Guide

Spring‑Retry Framework

Spring Retry provides declarative retry support for Spring applications, useful in batch processing, Spring Integration, Hadoop, and other scenarios where operations may throw exceptions and need controlled retries.

1. Basic Usage

Preparation

Add the Maven dependency:

<dependency>
  <groupId>org.springframework.retry</groupId>
  <artifactId>spring-retry</artifactId>
  <version>1.2.2.RELEASE</version>
</dependency>

Create a task method that randomly throws exceptions or returns values:

package com.zgd.demo.thread.retry;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomUtils;
import org.springframework.remoting.RemoteAccessException;

@Slf4j
public class RetryDemoTask {
    public static boolean retryTask(String param) {
        log.info("Received param:{}", param);
        int i = RandomUtils.nextInt(0, 11);
        log.info("Random number:{}", i);
        if (i == 0) {
            log.info("Zero, throw IllegalArgumentException");
            throw new IllegalArgumentException("Parameter error");
        } else if (i == 1) {
            log.info("One, return true");
            return true;
        } else if (i == 2) {
            log.info("Two, return false");
            return false;
        } else {
            log.info("Greater than 2, throw RemoteAccessException");
            throw new RemoteAccessException("Remote access error");
        }
    }
}

2. Using SpringRetryTemplate

Configure a RetryTemplate with a retry policy and a back‑off policy:

RetryTemplate retryTemplate = new RetryTemplate();
FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy();
backOffPolicy.setBackOffPeriod(1000L); // 1 second
SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(3, exceptionMap);
retryTemplate.setRetryPolicy(retryPolicy);
retryTemplate.setBackOffPolicy(backOffPolicy);

Execute the retry logic:

Boolean result = retryTemplate.execute(
    retryContext -> {
        boolean b = RetryDemoTask.retryTask("abc");
        log.info("Result:{}", b);
        return b;
    },
    retryContext -> {
        log.info("Max attempts reached or non‑retryable exception");
        return false;
    }
);
log.info("Final result:{}", result);

The framework provides several built‑in retry policies such as NeverRetryPolicy , AlwaysRetryPolicy , SimpleRetryPolicy , TimeoutRetryPolicy , ExceptionClassifierRetryPolicy , CircuitBreakerRetryPolicy , and CompositeRetryPolicy . Back‑off strategies include NoBackOffPolicy , FixedBackOffPolicy , UniformRandomBackOffPolicy , ExponentialBackOffPolicy , and ExponentialRandomBackOffPolicy . Images illustrating the flow are shown below:

3. Annotation‑Based Usage

Add @EnableRetry to the Spring Boot application class and use @Retryable on methods that need retry, together with @Recover for fallback logic.

@EnableRetry
public class Application { ... }

@Service
@Slf4j
public class SpringRetryDemo {
    @Retryable(value = RemoteAccessException.class, maxAttempts = 3,
               backoff = @Backoff(delay = 2000L, multiplier = 2))
    public boolean call(String param) {
        return RetryDemoTask.retryTask(param);
    }

    @Recover
    public boolean recover(Exception e, String param) {
        log.error("Max attempts reached or non‑retryable exception", e);
        return false;
    }
}

Test the service with a SpringBootTest:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
@Slf4j
public class SpringRetryDemoTest extends MyBaseTest {
    @Autowired
    private SpringRetryDemo springRetryDemo;

    @Test
    public void retry() {
        boolean result = springRetryDemo.call("abc");
        log.info("--Result:{}--", result);
    }
}

Guava‑Retry Framework

Guava‑Retry offers similar functionality with more flexible retry sources, allowing retries based on exceptions or method return values.

Add the Maven dependency:

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

Build a Retryer that retries on RemoteAccessException or when the result is false:

Retryer<Boolean> retryer = RetryerBuilder.<Boolean>newBuilder()
    .retryIfExceptionOfType(RemoteAccessException.class)
    .retryIfResult(res -> res == false)
    .withWaitStrategy(WaitStrategies.fixedWait(3, TimeUnit.SECONDS))
    .withStopStrategy(StopStrategies.stopAfterAttempt(3))
    .build();

try {
    retryer.call(() -> RetryDemoTask.retryTask("abc"));
} catch (Exception e) {
    e.printStackTrace();
}

Guava‑Retry also supports policies such as retryIfException, retryIfRuntimeException, retryIfExceptionOfType, retryIfResult, and listeners via RetryListener to log each attempt.

Conclusion

Both Spring‑Retry and Guava‑Retry are thread‑safe and suitable for concurrent scenarios. They decouple normal logic from retry logic, support timeout, retry count, interval configuration, and listeners. Guava‑Retry is more convenient for result‑based retries, while Spring‑Retry focuses on exception‑based retries.

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.

Spring RetryGuava RetryRetry Policy
Programmer DD
Written by

Programmer DD

A tinkering programmer and author of "Spring Cloud Microservices in Action"

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.