ReusableCircuitBreaker.java
package net.secodo.jcircuitbreaker.breaker.impl;
import java.util.concurrent.Callable;
import net.secodo.jcircuitbreaker.breaker.builder.impl.ReusableCircuitBreakerBuilder;
import net.secodo.jcircuitbreaker.breakhandler.BreakHandler;
import net.secodo.jcircuitbreaker.breakhandler.exception.BreakHandlerException;
import net.secodo.jcircuitbreaker.breakstrategy.BreakStrategy;
import net.secodo.jcircuitbreaker.exception.CircuitBreakerException;
import net.secodo.jcircuitbreaker.exception.TaskExecutionException;
import net.secodo.jcircuitbreaker.task.Task;
/**
* An abstract implementation of {@link net.secodo.jcircuitbreaker.breaker.CircuitBreaker} which stores its
* {@link BreakStrategy} and {@link BreakHandler} as fields, so that there is no need to pass them each time. This has
* following consequence: both <i>break strategy</i> and <i>break handler</i> will be shared between different
* executions of <i>target-method</i>, so they should be "stateless". If this is not guaranteed
* (for each Task (runtime method) different instances of {@link BreakHandler}) should be created)
* than {@link net.secodo.jcircuitbreaker.breakhandler.BreakHandlerFactory} should be used.
*
* @param <R> the return type of the called method
*/
public class ReusableCircuitBreaker<R> extends AbstractCircuitBreaker<R> {
private final BreakStrategy<R> breakStrategy;
private final BreakHandler<R> breakHandler;
/**
* Constructs new breaker with given break strategy and break handler. Break strategy and break handler will be
* applied to each execution of the circuit breaker.
*
* @param breakStrategy a break strategy to apply to each Task executed by this circuit breaker
* @param breakHandler a break handler to apply fallback value (or fallback behaviour) when execution of task is
* prohibited by break strategy
*/
public ReusableCircuitBreaker(BreakStrategy<R> breakStrategy, BreakHandler<R> breakHandler) {
super();
this.breakStrategy = breakStrategy;
this.breakHandler = breakHandler;
}
/**
* Builder for {@link ReusableCircuitBreaker}. Allows to create {@link ReusableCircuitBreaker} in a
* fluent-interface way.
*
* @return an instance of builder which is used to construct {@link ReusableCircuitBreaker}
*/
@SuppressWarnings("rawtypes") // for convenience in usage
public static ReusableCircuitBreakerBuilder builder() {
return new ReusableCircuitBreakerBuilder();
}
/**
* Builder for {@link ReusableCircuitBreaker}. Allows to create {@link ReusableCircuitBreaker} in a
* fluent-interface way. This method is parameterized and requires return type of java <i>target-method</i> to be
* defined while calling this method.
*
* @param <R> the return type or <i>target-method</i> to be executed by circuit breaker
* @return an instance of builder which is used to construct {@link ReusableCircuitBreaker}
*/
public static <R> ReusableCircuitBreakerBuilder<R> builderP() {
return new ReusableCircuitBreakerBuilder<>();
}
/**
* Executes given Task within this breaker using {@link BreakStrategy} and {@link BreakHandler} given as the params.
*
* @param task the real-method to be executed
* @return the output value of the real method
* @see net.secodo.jcircuitbreaker.breaker.CircuitBreaker#execute(Task, BreakStrategy, BreakHandler)
*
* @throws TaskExecutionException if execution of given Task results in exception
*/
public R execute(Task<R> task) throws TaskExecutionException, CircuitBreakerException, BreakHandlerException {
return super.execute(task, breakStrategy, breakHandler);
}
/**
* Executes given Task within this breaker using {@link BreakStrategy} and {@link BreakHandler} given as the params
* with custom data passed as userData param.
*
* @param task the real-method to be executed
* @param userData custom object with data which will be made available to break strategy and break handler via
* execution context
* @param <U> the type of user data object which will be made available to break strategy and break handler via
* execution context
* @return the output value of the real method
*
* @see net.secodo.jcircuitbreaker.breaker.CircuitBreaker#execute(Task, BreakStrategy, BreakHandler, Object)
*
* @throws TaskExecutionException if execution of given Task results in exception
*/
public <U> R execute(Task<R> task, U userData) throws TaskExecutionException, CircuitBreakerException,
BreakHandlerException {
return super.execute(task, breakStrategy, breakHandler, userData);
}
}