package dk.thoerup.curcuitbreaker; import dk.thoerup.curcuitbreaker.notification.Notifier; import dk.thoerup.curcuitbreaker.notification.NullNotifier; /* Simple CircuitBreaker implementation - snipped from http://www.jroller.com/kenwdelong/entry/circuit_breaker_in_java * * example of how it can be used private CircuitBreaker cb = new CircuitBreaker("test", 5, 10000); protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { class TestInvocation implements CircuitInvocation { String url; public TestInvocation(String url) { this.url = url; } public Object proceed() throws Exception{ URL u = new URL(url); URLConnection c = u.openConnection(); c.connect(); InputStream in = c.getInputStream(); in.close(); return "hello"; } } try { String s = (String) cb.invoke(new TestInvocation("http://rafiki/test")); response.getWriter().print(s); } catch (Throwable e) { logger.warning( e.getMessage() ); response.sendError(500); return; } } */ public class CircuitBreaker{ private volatile CircuitBreakerState currentState; private final OpenState open = new OpenState(); private final HalfOpenState halfOpen = new HalfOpenState(); private final ClosedState closed = new ClosedState(); private String name; private Notifier notifier = new NullNotifier(); public CircuitBreaker(String name, int threshold, long timeoutMS) { closed.setThreshold(threshold); open.setTimeout(timeoutMS); this.name = name; reset(); } public Object invoke(CircuitInvocation invocation) throws Exception { Object result = null; try { getState().preInvoke(this); result = invocation.proceed(); getState().postInvoke(this); } catch(Exception e) { getState().onError(this, e); throw e; } return result; } public void tripBreaker() { synchronized(this) { if (currentState != open) { // TODO:Is this conditional necessary ?? open.trip(); currentState = open; notifier.sendNotification(name, Notifier.Event.BreakerTripped); } } } public void attemptReset() { synchronized(this) { if (currentState != halfOpen) { // TODO:Is this conditional necessary ?? currentState = halfOpen; notifier.sendNotification(name, Notifier.Event.BreakerAttemptReset); } } } public void reset() { synchronized(this) { if (currentState != closed) { // TODO: Is this conditional necessary ?? currentState = closed; notifier.sendNotification(name, Notifier.Event.BreakerReset); } } } private CircuitBreakerState getState() { synchronized(this) { return currentState; } } public boolean isClosed() { return (getState() == closed); } public boolean isOpen() { return (getState() == open); } public String getName() { return name; } public String getStateName() { return getState().getName(); } public int getThreshold() { return closed.getThreshold(); } public int getTimeout() { return (int)open.getTimeout(); } public int getFailureCount() { if (getState() == closed) { return closed.getFailureCount(); } else { return -1; } } public long getElapsed() { if (getState() == open) { return open.getElapsed(); } else { return -1; } } public void setNotifier(Notifier notifier) { this.notifier = notifier; } public String getNotifierName() { return notifier.getClass().getName(); } }