MethodInvokingTask.java

package net.secodo.jcircuitbreaker.task.experimental;

import java.lang.reflect.Method;

import net.secodo.jcircuitbreaker.task.Task;


/**
 * Explicitly encapsulates and object and method of the object which should be executed by <i>circuit breaker</i>.
 * This class is experimental - it may change or be removed in future releases.
 * 
 * @param <R> return type of the class
 * @param <T> the type/class of the object which contains the method that should be executed 
 */
public class MethodInvokingTask<R, T> implements Task<R> {
  private final T object;
  private final Object[] methodParams;
  private final Method method;

  /**
   * Constructs new Task which invokes method with given name and method arguments on given object.
   *
   * @param object the object which contains the method with given name
   * @param methodName the name of the method which should be executed
   * @param methodReturnType class representing the return value of the method.
   * @param methodParams the arguments which should be passed to the method
   * @throws NoSuchMethodException if such method can not be found
   */
  public MethodInvokingTask(T object, String methodName, Class<R> methodReturnType, Object... methodParams)
                     throws NoSuchMethodException {
    this.object = object;
    this.methodParams = methodParams;

    Class<?>[] methodParamTypes = new Class[methodParams.length];

    for (int i = 0; i < methodParams.length; i++) {
      methodParamTypes[i] = methodParams[i].getClass();
    }

    method = object.getClass().getDeclaredMethod(methodName, methodParamTypes);

    final Class<?> returnType = method.getReturnType();

    if (methodReturnType != returnType) {
      throw new NoSuchMethodException(
        "Given method return type: " + returnType + " does not match wanted return " +
        "type: " + methodReturnType);
    }

  }


  @Override
  @SuppressWarnings("unchecked")
  public R execute() throws Exception {
    return (R) method.invoke(object, methodParams);
  }
}