@Override
  public ContainerResponse apply(final ContainerRequest requestContext) {
    final Object resource = routingContextFactory.get().peekMatchedResource();

    final ProcessingContext processingCtx = invocationContextFactory.get();
    if (method.isSuspendDeclared()) {
      processingCtx.setSuspendTimeout(method.getSuspendTimeout(), method.getSuspendTimeoutUnit());
    }
    requestContext.setProperty(ReaderInterceptorExecutor.INTERCEPTORS, getReaderInterceptors());
    requestContext.setProperty(WriterInterceptorExecutor.INTERCEPTORS, getWriterInterceptors());
    final Response response = dispatcher.dispatch(resource, requestContext);

    if (method.isSuspendDeclared()) {
      processingCtx.setResponse(resource);
      processingCtx.trySuspend();
    }

    final ContainerResponse responseContext = new ContainerResponse(requestContext, response);
    final Invocable invocable = method.getInvocable();
    responseContext.setEntityAnnotations(invocable.getHandlingMethod().getDeclaredAnnotations());

    if (responseContext.hasEntity()
        && !(responseContext.getEntityType() instanceof ParameterizedType)) {
      Type invocableType = invocable.getResponseType();
      if (invocableType != null
          && Void.TYPE != invocableType
          && Void.class != invocableType
          && invocableType != Response.class) {
        responseContext.setEntityType(invocableType);
      }
    }

    return responseContext;
  }
  private ResourceMethodInvoker(
      Provider<RoutingContext> routingContextFactory,
      Provider<ProcessingContext> invocationContextFactory,
      ResourceMethodDispatcher.Provider dispatcherProvider,
      ResourceMethodInvocationHandlerProvider invocationHandlerProvider,
      ResourceMethod method,
      MultivaluedMap<Class<? extends Annotation>, ContainerRequestFilter> nameBoundRequestFilters,
      MultivaluedMap<Class<? extends Annotation>, ContainerResponseFilter> nameBoundResponseFilters,
      Collection<ReaderInterceptor> globalReaderInterceptors,
      Collection<WriterInterceptor> globalWriterInterceptors,
      MultivaluedMap<Class<? extends Annotation>, ReaderInterceptor> nameBoundReaderInterceptors,
      MultivaluedMap<Class<? extends Annotation>, WriterInterceptor> nameBoundWriterInterceptors,
      Collection<DynamicBinder> dynamicBinders) {

    this.routingContextFactory = routingContextFactory;
    this.invocationContextFactory = invocationContextFactory;

    this.method = method;
    final Invocable invocable = method.getInvocable();
    this.dispatcher =
        dispatcherProvider.create(invocable, invocationHandlerProvider.create(invocable));

    this.resourceMethod = invocable.getHandlingMethod();
    this.resourceClass = invocable.getHandler().getHandlerClass();

    List<ReaderInterceptor> _readerInterceptors = new LinkedList<ReaderInterceptor>();
    List<WriterInterceptor> _writerInterceptors = new LinkedList<WriterInterceptor>();

    for (DynamicBinder dynamicBinder : dynamicBinders) {
      Object boundProvider = dynamicBinder.getBoundProvider(this);

      // TODO: should be based on the type arg. value rather than instanceof?
      if (boundProvider instanceof WriterInterceptor) {
        _writerInterceptors.add((WriterInterceptor) boundProvider);
      }

      if (boundProvider instanceof ReaderInterceptor) {
        _readerInterceptors.add((ReaderInterceptor) boundProvider);
      }

      if (boundProvider instanceof ContainerRequestFilter) {
        this.requestFilters.add((ContainerRequestFilter) boundProvider);
      }

      if (boundProvider instanceof ContainerResponseFilter) {
        this.responseFilters.add((ContainerResponseFilter) boundProvider);
      }
    }

    _readerInterceptors.addAll(globalReaderInterceptors);
    _writerInterceptors.addAll(globalWriterInterceptors);

    if (resourceMethod != null) {
      addNameBoundFiltersAndInterceptors(
          nameBoundRequestFilters,
          nameBoundResponseFilters,
          nameBoundReaderInterceptors,
          nameBoundWriterInterceptors,
          this.requestFilters,
          this.responseFilters,
          _readerInterceptors,
          _writerInterceptors,
          method);
    }

    Collections.sort(
        _readerInterceptors,
        new PriorityComparator<ReaderInterceptor>(PriorityComparator.Order.ASCENDING));
    Collections.sort(
        _writerInterceptors,
        new PriorityComparator<WriterInterceptor>(PriorityComparator.Order.ASCENDING));

    this.readerInterceptors = Collections.unmodifiableList(_readerInterceptors);
    this.writerInterceptors = Collections.unmodifiableList(_writerInterceptors);
  }