Failsafe Fallback Policy

September 13, 2020 No comments Failsafe Java library Fallback policy

1. Introduction

In this article, we are going to present the Fallback policy available in Failsafe library. Fallbacks allow you to provide an alternative result for a failed execution.

2. Basic use

The most basic use is to set a default result object of any kind as a fallback:

Fallback<Object> fallback = Fallback.of(defaultResult);

We could also throw a new custom exception:

Fallback<Object> fallback = Fallback.ofException(e -> new CustomException(e.getLastFailure()));

Or compute an alternative result such as from a backup resource:

Fallback<Object> fallback = Fallback.of(this::connectToBackup);

A CompletionStage can be supplied as a fallback:

Fallback<Object> fallback = Fallback.ofStage(this::connectToBackup);

And for computations that block, a Fallback can be configured to run asynchronously:

Fallback<Object> fallback = Fallback.ofAsync(this::blockingCall);

3. Event listeners

Fallbacks support event listeners that can tell you when an execution attempt failed:

fallback.onFailedAttempt(e -> log.error("Connection failed", e.getLastFailure()))
fallback.onFailure(e -> log.error("Failed to connect to backup", e.getFailure()));
fallback.onSuccess(e -> log.info("Connection established"));

4. JUnit test

The following JUnit test makes the use of the Fallback policy. We set the fallback to another object. When an error occurs Failsafe library will choose an alternative result object:

package com.frontbackend.libraries.failsafe;

import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.net.ConnectException;
import java.util.Date;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;

import net.jodah.failsafe.Failsafe;
import net.jodah.failsafe.Fallback;

@RunWith(MockitoJUnitRunner.class)
public class FallbackPolicyTest {

    @Mock
    DatabaseConnection connection = new DatabaseConnection();

    @Test
    public void testFallback() throws ConnectException {
        // given
        DatabaseConnection result = null;
        DatabaseConnection other = new DatabaseConnection("other");
        Fallback<Object> fallback = Fallback.of(other);
        fallback.onFailedAttempt(e -> log(String.format("Connection failed%s", e.getLastFailure())));
        fallback.onFailure(e -> log(String.format("Failed to connect to backup%s", e.getFailure())));
        fallback.onSuccess(e -> log(String.format("Connection established %s", e.getResult())));

        // when
        when(connection.connect()).thenThrow(ConnectException.class);

        Failsafe.with(fallback)
                .run(connection::connect);

        // then
        verify(connection, Mockito.times(1)).connect();
    }

    private void log(String log) {
        System.out.printf("%s : %s%n", new Date(), log);
    }
}

5. Conclusion

This article shows the simplest way to use the Fallback policy using Failsafe library. Fallback allows us to give an alternative result if execution failed.

{{ message }}

{{ 'Comments are closed.' | trans }}