protected Object _invoke(
      Method callMethod,
      Method runMethod,
      Object[] args,
      Instance instance,
      ThreadContext callContext,
      InterfaceType callType)
      throws OpenEJBException {
    BeanContext beanContext = callContext.getBeanContext();

    Duration accessTimeout = getAccessTimeout(beanContext, runMethod);
    boolean read = beanContext.getConcurrencyAttribute(runMethod) == javax.ejb.LockType.READ;

    final Lock lock = aquireLock(read, accessTimeout, instance, runMethod);

    Object returnValue;
    try {
      TransactionPolicy txPolicy =
          createTransactionPolicy(
              beanContext.getTransactionType(callMethod, callType), callContext);

      returnValue = null;
      try {
        if (callType == InterfaceType.SERVICE_ENDPOINT) {
          callContext.setCurrentOperation(Operation.BUSINESS_WS);
          returnValue = invokeWebService(args, beanContext, runMethod, instance);
        } else {
          List<InterceptorData> interceptors = beanContext.getMethodInterceptors(runMethod);
          InterceptorStack interceptorStack =
              new InterceptorStack(
                  instance.bean,
                  runMethod,
                  callType == InterfaceType.TIMEOUT ? Operation.TIMEOUT : Operation.BUSINESS,
                  interceptors,
                  instance.interceptors);
          returnValue = interceptorStack.invoke(args);
        }
      } catch (Throwable e) { // handle reflection exception
        ExceptionType type = beanContext.getExceptionType(e);
        if (type == ExceptionType.SYSTEM) {
          /* System Exception ****************************/

          // The bean instance is not put into the pool via instanceManager.poolInstance
          // and therefore the instance will be garbage collected and destroyed.
          // For this reason the discardInstance method of the StatelessInstanceManager
          // does nothing.
          handleSystemException(txPolicy, e, callContext);
        } else {
          /* Application Exception ***********************/

          handleApplicationException(txPolicy, e, type == ExceptionType.APPLICATION_ROLLBACK);
        }
      } finally {
        afterInvoke(txPolicy, callContext);
      }
    } finally {
      lock.unlock();
    }

    return returnValue;
  }