/**
   * 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();
    }
  }
  public final void processResponseInternal(BaseMessageContextImpl ctx) {
    MessageContextAccessorImpl.blockPreviousContext();
    try {
      ServiceDesc serviceDesc = ctx.getServiceDesc();
      try {
        Dispatcher requestDispatcher = serviceDesc.getRequestDispatcher();
        requestDispatcher.retrieve(ctx, ctx.getFutureResponse());

      } catch (Throwable e) {
        handleRequestDispatchException(ctx, e);
        handleAbortedRequestDispatch(ctx);
      }

      runResponseSequence(ctx);
      Long processingStartTime =
          (Long) ctx.getProperty(SystemMetricDefs.CTX_KEY_MSG_PROCESSING_STARTED);
      updateMonitoringAfterProcessing(ctx, processingStartTime.longValue());
    } finally {
      MessageContextAccessorImpl.resetContext();
    }
  }