/**
   * Invoke handlers, protocol processor and dispatchers for the given context NOTE: async
   * processing logic has been removed for SOA 2.0. Async processing logic will be reintroduced post
   * SOA 2.0.
   */
  @SuppressWarnings("unchecked")
  public final void processMessageInternal(BaseMessageContextImpl ctx, boolean useAsync) {
    MessageContextAccessorImpl.blockPreviousContext();
    try {
      long processingStartTime = System.nanoTime();
      // Pass the start time into ctx for later reference
      recordMessageProcessingStartTime(ctx, processingStartTime);

      // run request pipeline
      runRequestSequence(ctx);

      // give it to request dispatcher
      if (!ctx.hasErrors() && !ctx.hasResponseResidentErrors()) {
        try {
          dispatchInternal(ctx, useAsync);
        } catch (Throwable e) {
          handleRequestDispatchException(ctx, e);
          handleAbortedRequestDispatch(ctx);
        }
      } else {
        handleAbortedRequestDispatch(ctx);
      }

      if (!useAsync) {
        // run response pipeline in case of sync executions or pipeline
        // errors
        runResponseSequence(ctx);
        updateMonitoringAfterProcessing(ctx, processingStartTime);
      }
    } finally {
      MessageContextAccessorImpl.resetContext();
    }
  }
  protected boolean shouldCountAsFailedRequest(BaseMessageContextImpl ctx) {

    if (ctx.hasErrors()) return true;
    if (!ctx.hasResponseResidentErrors()) return false;

    /** RRE's only count as failed requests if the severity was severe enough */
    List<ErrorData> errorDataList = ctx.getResponseResidentErrorList();
    for (ErrorData errorData : errorDataList) if (isError(errorData)) return true;

    return false;
  }