adam bien's blog

A Minimalistic Circuit Breaker Pattern Implementation For Java EE 📎

The Circuit Breakr Pattern aims to open the "circuit" after hitting a configurable threshold of erroneous method calls.

A natural fit is the use of an interceptor to measure the performance and monitor the exceptions. After reaching the threshold the interceptor returns without calling the target:


public class Breakr {

    private long errorCounter;
    private static final int FAILURES_COUNT = 5;
    private static final int TIMEOUT_IN_MS = 1000;

    @AroundInvoke
    public Object guard(InvocationContext ic) throws Exception {
        long maxNbrOfFailures = FAILURES_COUNT;
        long timeout = TIMEOUT_IN_MS;

        IgnoreCallsWhen configuration = ic.
                getMethod().
                getAnnotation(IgnoreCallsWhen.class);

        if (configuration != null) {
            maxNbrOfFailures = configuration.failures();
            timeout = configuration.slowerThanMillis();
        }

        long start = System.currentTimeMillis();
        try {
            if (errorCounter >= maxNbrOfFailures) {
                return null;
            }
            return ic.proceed();
        } catch (Exception ex) {
            errorCounter++;
            throw ex;
        } finally {
            long duration = System.currentTimeMillis() - start;
            if (duration >= timeout) {
                errorCounter++;
            }
        }
    }

}

The threshold can be easily configured with an annotation:


@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface IgnoreCallsWhen {

    long slowerThanMillis() default 1000;

    long failures() default 3;
}

Usage example:


@Singleton
@Interceptors(Breakr.class)
public class Slow {

    @IgnoreCallsWhen(slowerThanMillis = 10)
    public String tooSlow() {
        try {
            Thread.sleep(100);
        } catch (InterruptedException ex) {}
        return "Slow: " + System.currentTimeMillis();
    }

}

The source is available from github.com/AdamBien/breakr.

Use the following maven dependency to install breakr:


<dependency>
	<groupId>com.airhacks</groupId>
	<artifactId>breakr</artifactId>
	<version>[CURRENT_VERSION]</version>
</dependency>

See you at Java EE Workshops at Munich Airport, Terminal 2 particularly in Java EE Microservices. Is Munich's airport too far? Learn from home: airhacks.io.