View Javadoc
1   package net.secodo.jcircuitbreaker.breakhandler;
2   
3   import static java.util.Objects.isNull;
4   
5   import java.util.concurrent.Callable;
6   
7   import net.secodo.jcircuitbreaker.breaker.ContextAwareCircuitBreaker;
8   import net.secodo.jcircuitbreaker.breaker.execution.ExecutionContext;
9   import net.secodo.jcircuitbreaker.breakhandler.exception.BreakHandlerException;
10  import net.secodo.jcircuitbreaker.breakstrategy.BreakStrategy;
11  import net.secodo.jcircuitbreaker.exception.CircuitBreakerException;
12  import net.secodo.jcircuitbreaker.exception.TaskExecutionException;
13  import net.secodo.jcircuitbreaker.task.Task;
14  
15  
16  /**
17   * This is generic factory method interface. Each implementation should implement 
18   * {@link #makeHandler(Task, ExecutionContext)} method which returns instance of a {@link BreakHandler}. The
19   * returned instance should be shareable between different executions of the target-method (between execution of
20   * different tasks). This means that the implementation should conform to one of following statements:
21   * <ul>
22   * <li>should be stateless - the returned handler should not allow modification of its internal state. This prevents
23   * possible {@link java.util.ConcurrentModificationException} when accessed by different threads</li>
24   * <li>should return new instance (but the instances may not share a common state via static fields etc. which may
25   * result in {@link java.util.ConcurrentModificationException} when accessed by different threads)</li>
26   * <li>may share state (or be the same instance) as long as any possible concurrent modifications are protected by
27   * synchronization/locking mechanism, so that multiple threads can access the instance on the same time</li>
28   * </ul>
29   *
30   * @param <R> the return type of onBreak method of the created {@link BreakHandler}. This must be the same return
31   *            type as the of of executed Task
32   */
33  public interface BreakHandlerFactory<R> extends BreakHandler<R> {
34    @Override
35    default R onBreak(ContextAwareCircuitBreaker<R> circuitBreaker, Task<R> task, BreakStrategy<R> breakStrategy,
36                      ExecutionContext<R> executionContext) throws TaskExecutionException, CircuitBreakerException,
37                                                                   BreakHandlerException {
38      BreakHandler<R> handler = makeHandler(task, executionContext);
39      if (isNull(handler)) {
40        throw new BreakHandlerException("makeHandler() method returned handler which is null");
41      }
42  
43      return handler.onBreak(circuitBreaker, task, breakStrategy, executionContext);
44    }
45  
46    /**
47     * Returns an instance of {@link BreakHandler} which should be used to handle the <i>break</i>.
48     *
49     * @param task             the task which is executed by this {@link BreakHandler}
50     * @param executionContext contains current execution data (specific to current execution)
51     * @return an instance of {@link BreakHandler}
52     * @throws BreakHandlerException when the handler could not have been produced
53     */
54    BreakHandler<R> makeHandler(Task<R> task, ExecutionContext<R> executionContext) throws BreakHandlerException;
55  }