Basic Usage

Installation

As an application developer, you don’t have to "install" SmallRye Fault Tolerance in any way. Your chosen runtime, such as Quarkus or WildFly, already integrates SmallRye Fault Tolerance to provide MicroProfile Fault Tolerance. Please refer to the documentation of your selected runtime to understand how to enable MicroProfile Fault Tolerance.

If you are a framework developer, interested in integrating SmallRye Fault Tolerance, please refer to the integration chapter.

Annotations

MicroProfile Fault Tolerance is built on top of CDI and interceptors. This lets you guard method calls with selected fault tolerance strategies simply by annotating a CDI bean class or method with one of the fault tolerance annotations. For example:

@ApplicationScoped (1)
public class MyService {
    @Retry (2)
    public String hello() {
        ...
    }
}
1 @ApplicationScoped is a bean defining annotation. It makes the MyService class a CDI bean.
2 @Retry is a fault tolerance annotation. It could also be placed on the class, in which case it would apply to all methods in the class.

Here, if the hello method throws an exception, the invocation will be retried several times, until the method returns a value.

CDI beginners often expect that this will work if you create an instance manually: new MyService(). That is not the case. You have to let the CDI container construct an instance for you and inject it: @Inject MyService service. What you get injected is actually a proxy that implements the additional behaviors.

The fault tolerance strategies present in MicroProfile Fault Tolerance, together with the corresponding annotations, are:

  • @Asynchronous: offload method execution to another thread

  • @Bulkhead: limit concurrent invocations

  • @CircuitBreaker: prevent invocations if previous invocations failed too often

  • @Fallback: provide alternative result in case of a failure

  • @Retry: retry several times in case of a failure

  • @Timeout: fail if the invocation takes too long

We won’t go into detail here. This is all described in the MicroProfile Fault Tolerance specification.

Configuration

The fault tolerance strategies can be configured using annotation attributes, such as:

@ApplicationScoped
public class MyService {
    @Retry(maxRetries = 10, retryOn = IOException.class) (1)
    public String hello() {
        ...
    }
}
1 Retries will only be attempted if the thrown exception was IOException. Other exceptions will be rethrown directly. Also the maximum number of retry attempts is changed to 10 (the default is 3).

This is convenient, but changing such configuration requires recompilation. For that reason, MicroProfile Fault Tolerance also allows configuration using MicroProfile Config. For example:

com.example.MyService/hello/Retry/maxRetries=5

Again, this is all described in the MicroProfile Fault Tolerance specification, so we won’t go into detail here.

Metrics

The MicroProfile Fault Tolerance specification describes how implementations should expose metrics over MicroProfile Metrics. As usual, this is described in the MicroProfile Fault Tolerance specification.

Micrometer

In addition to the MicroProfile Metrics support, demanded by the MicroProfile Fault Tolerance specification, SmallRye Fault Tolerance also provides support for Micrometer. The set of metrics emitted to Micrometer is the same as the set of metrics emitted to MicroProfile Metrics, using the same metric names and tags. Metric types are mapped as closely as possible:

Name MicroProfile Metrics Micrometer

ft.invocations.total

counter

counter

ft.retry.calls.total

counter

counter

ft.retry.retries.total

counter

counter

ft.timeout.calls.total

counter

counter

ft.timeout.executionDuration

histogram

timer

ft.circuitbreaker.calls.total

counter

counter

ft.circuitbreaker.state.total

gauge

time gauge

ft.circuitbreaker.opened.total

counter

counter

ft.bulkhead.calls.total

counter

counter

ft.bulkhead.executionsRunning

gauge

gauge

ft.bulkhead.executionsWaiting

gauge

gauge

ft.bulkhead.runningDuration

histogram

timer

ft.bulkhead.waitingDuration

histogram

timer

ft.ratelimit.calls.total

counter

counter

Note that distribution summaries in Micrometer, including timers, do not emit quantile buckets by default. Micrometer recommends that libraries should not configure them out of the box, so if you need them, you should use a MeterFilter.

The following implementation makes sure Micrometer emits the same quantile buckets as MicroProfile Metrics for all fault tolerance metrics:

static final MeterFilter ENABLE_HISTOGRAMS = new MeterFilter() {
    @Override
    public DistributionStatisticConfig configure(Meter.Id id, DistributionStatisticConfig config) {
        if (id.getName().startsWith("ft.")) {
            return DistributionStatisticConfig.builder()
                    .percentiles(0.5, 0.75, 0.95, 0.98, 0.99, 0.999)
                    .build()
                    .merge(config);
        }
        return config;
    }
};