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.