SkillAgentSearch skills...

Retry4j

Lightweight Java library for retrying unreliable logic - DEPRECATED

Install / Use

/learn @elennick/Retry4j

README

Coverage Status Maven Central License: MIT

DEPRECATED

Retry4j is no longer maintained and has had no releases for several years. Please feel free to fork and make your own changes/releases if you want to build upon it. Also consider checking out more modern libraries such as:

  • Failsafe - https://github.com/jhalterman/failsafe
  • Spring Retry - https://github.com/spring-projects/spring-retry
  • resilience4j - https://github.com/resilience4j/resilience4j

Retry4j

Retry4j is a simple Java library to assist with retrying transient failure situations or unreliable code. Retry4j aims to be readable, well documented and streamlined.

Table of Contents

Basic Code Examples

Handling Failures with Exceptions

Callable<Object> callable = () -> {
    //code that you want to retry until success OR retries are exhausted OR an unexpected exception is thrown
};

RetryConfig config = new RetryConfigBuilder()
        .retryOnSpecificExceptions(ConnectException.class)
        .withMaxNumberOfTries(10)
        .withDelayBetweenTries(30, ChronoUnit.SECONDS)
        .withExponentialBackoff()
        .build();
        
try {  
    Status<Object> status = new CallExecutorBuilder()
        .config(config)
        .build()
        .execute(callable);
    Object object = status.getResult(); //the result of the callable logic, if it returns one
} catch(RetriesExhaustedException ree) {
    //the call exhausted all tries without succeeding
} catch(UnexpectedException ue) {
    //the call threw an unexpected exception
}

Or more simple using one of the predefined config options and not checking exceptions:

Callable<Object> callable = () -> {
    //code that you want to retry
};

RetryConfig config = new RetryConfigBuilder()
    .exponentialBackoff5Tries5Sec()
    .build();

Status<Object> status = new CallExecutorBuilder().config(config).build().execute(callable);

Handling All Results with Listeners

Callable<Object> callable = () -> {
    //code that you want to retry
};

RetryConfig config = new RetryConfigBuilder()
        .exponentialBackoff5Tries5Sec()
        .build();

CallExecutor executor = new CallExecutorBuilder<>()
        .config(config).
        .onSuccess(s -> { //do something on success })
        .onFailure(s -> { //do something after all retries are exhausted })
        .afterFailedTry(s -> { //do something after a failed try })
        .beforeNextTry(s -> { //do something before the next try })
        .onCompletion(s -> { //do some cleanup })
        .build();
        
executor.execute(callable);

Dependencies

Maven

<dependency>
    <groupId>com.evanlennick</groupId>
    <artifactId>retry4j</artifactId>
    <version>0.15.0</version>
</dependency>

SBT

libraryDependencies += "com.evanlennick" % "retry4j" % "0.15.0"

Gradle

compile "com.evanlennick:retry4j:0.15.0"

Usage

General

Retry4j does not require any external dependencies. It does require that you are using Java 8 or newer.

  • Javadocs are hosted at: http://www.javadoc.io/doc/com.evanlennick/retry4j/0.15.0.
  • Continuous integration results are available via Travis CI here: https://travis-ci.org/elennick/retry4j.
  • Code coverage information is available via Coveralls here: https://coveralls.io/github/elennick/retry4j.
  • Examples of Retry4j in use are documented here: https://github.com/elennick/retry4j-examples

Exception Handling Config

If you do not specify how exceptions should be handled or explicitly say failOnAnyException(), the CallExecutor will fail and throw an UnexpectedException when encountering exceptions while running. Use this configuration if you want the executor to cease its work when it runs into any exception at all.

RetryConfig config = new RetryConfigBuilder()
        .failOnAnyException()
        .build();

If you want to specify specific exceptions that should cause the executor to continue and retry on encountering, do so using the retryOnSpecificExceptions() config method. This method can accept any number of exceptions if there is more than one that should indicate the executor should continue retrying. All other unspecified exceptions will immediately interupt the executor and throw an UnexpectedException.

RetryConfig config = new RetryConfigBuilder()
        .retryOnSpecificExceptions(ConnectException.class, TimeoutException.class)
        .build();

If you want the executor to continue to retry on all encountered exceptions, specify this using the retryOnAnyException() config option.

RetryConfig config = new RetryConfigBuilder()
        .retryOnAnyException()
        .build();

If you want the executor to continue to retry when encountered exception's cause is among a list of exceptions, then specify retryOnCausedBy() config option

RetryConfig config = new RetryConfigBuilder()
        .retryOnCausedBy()
        .retryOnSpecificExceptions(ConnectException.class, TimeoutException.class)
        .build();

If you want the executor to continue to retry on all encountered exceptions EXCEPT for a few specific ones, specify this using the retryOnAnyExceptionExcluding() config option. If this exception strategy is chosen, only the exceptions specified or their subclasses will interupt the executor and throw an UnexpectedException.

RetryConfig config = new RetryConfigBuilder()
        .retryOnAnyExceptionExcluding(CriticalFailure.class, DontRetryOnThis.class)
        .build();

NOTE: When using retryOnSpecificExceptions and retryOnAnyExceptionExcluding, the call executor will also take into account if the encountered exceptions are subclasses of the types you specified. For example, if you tell the configuration to retry on any IOException, the executor will retry on a FileNotFoundException which is a subclass of IOException.

If you do not want to use these built-in mechanisms for retrying on exceptions, you can override them and create custom logic:

RetryConfig config = new RetryConfigBuilder()
        .retryOnCustomExceptionLogic(ex -> {
            //return true to retry, otherwise return false
        })
        .build();

If you create custom exception logic, no other built-in retry-on-exception configuration can be used at the same time.

Value Handling Config

If you want the executor to retry based on the returned value from the Callable:

RetryConfig config = retryConfigBuilder
        .retryOnReturnValue("retry on this value!")
        .build();

This can be used in combination with exception handling configuration like so:

RetryConfig config = retryConfigBuilder
        .retryOnSpecificExceptions(FileNotFoundException.class)
        .retryOnReturnValue("retry on this value!")
        .build();

In the above scenario, the call execution will be considered a failure and a retry will be triggered if FileNotFoundException.class is thrown OR if the String retry on this value! is returned from the Callable logic.

To retry only using return values, you can disable exception retries using the failOnAnyException() configuration option:

RetryConfig config = retryConfigBuilder
        .failOnAnyException()
        .retryOnReturnValue("retry on this value!")
        .build();

Timing Config

To specify the maximum number of tries that should be attempted, specify an integer value in the config using the withMaxNumberOfTries() method. The executor will attempt to execute the call the number of times specified and if it does not succeed after all tries have been exhausted, it will throw a RetriesExhaustedException.

RetryConfig config = new RetryConfigBuilder()
        .withMaxNumberOfTries(5)
        .build();

If you do not wish to have a maximum and want retries to continue indefinitely, instead us the retryIndefinitely() option:

RetryConfig config = new RetryConfigBuilder()
        .retryIndefinitely()
        .build();

To specify the delay in between each try, use the withDelayBetweenTries() config method. This method will accept a Java 8 Duration object or an integer combined with a ChronoUnit.

//5 seconds
RetryConfig config = new RetryConfigBuilder()
        .withDelayBetweenTries(5, ChronoUnit.SECONDS)
        .build();

//2 minutes
RetryConfig config = new RetryConfigBuilder()
        .withDelayBetweenTries(Duration.of(2, ChronoUnit.MINUTES))
        .build();

//250 millis
RetryConfig config = new RetryConfigBuilder()
        .withDelayBetweenTries(Duration.ofMillis(250))
        .build();

Backoff Strategy Config

Retry4j has built in support for several backoff strategies. They

View on GitHub
GitHub Stars204
CategoryDevelopment
Updated10h ago
Forks27

Languages

Java

Security Score

100/100

Audited on Mar 23, 2026

No findings