001/*
002 * Copyright 2002-2017 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.web.servlet;
018
019import javax.servlet.http.HttpServletRequest;
020import javax.servlet.http.HttpServletResponse;
021
022import org.springframework.web.method.HandlerMethod;
023
024/**
025 * Extends {@code HandlerInterceptor} with a callback method invoked after the
026 * start of asynchronous request handling.
027 *
028 * <p>When a handler starts an asynchronous request, the {@link DispatcherServlet}
029 * exits without invoking {@code postHandle} and {@code afterCompletion} as it
030 * normally does for a synchronous request, since the result of request handling
031 * (e.g. ModelAndView) is likely not yet ready and will be produced concurrently
032 * from another thread. In such scenarios, {@link #afterConcurrentHandlingStarted}
033 * is invoked instead, allowing implementations to perform tasks such as cleaning
034 * up thread-bound attributes before releasing the thread to the Servlet container.
035 *
036 * <p>When asynchronous handling completes, the request is dispatched to the
037 * container for further processing. At this stage the {@code DispatcherServlet}
038 * invokes {@code preHandle}, {@code postHandle}, and {@code afterCompletion}.
039 * To distinguish between the initial request and the subsequent dispatch
040 * after asynchronous handling completes, interceptors can check whether the
041 * {@code javax.servlet.DispatcherType} of {@link javax.servlet.ServletRequest}
042 * is {@code "REQUEST"} or {@code "ASYNC"}.
043 *
044 * <p>Note that {@code HandlerInterceptor} implementations may need to do work
045 * when an async request times out or completes with a network error. For such
046 * cases the Servlet container does not dispatch and therefore the
047 * {@code postHandle} and {@code afterCompletion} methods will not be invoked.
048 * Instead, interceptors can register to track an asynchronous request through
049 * the {@code registerCallbackInterceptor} and {@code registerDeferredResultInterceptor}
050 * methods on {@link org.springframework.web.context.request.async.WebAsyncManager
051 * WebAsyncManager}. This can be done proactively on every request from
052 * {@code preHandle} regardless of whether async request processing will start.
053 *
054 * @author Rossen Stoyanchev
055 * @since 3.2
056 * @see org.springframework.web.context.request.async.WebAsyncManager
057 * @see org.springframework.web.context.request.async.CallableProcessingInterceptor
058 * @see org.springframework.web.context.request.async.DeferredResultProcessingInterceptor
059 */
060public interface AsyncHandlerInterceptor extends HandlerInterceptor {
061
062        /**
063         * Called instead of {@code postHandle} and {@code afterCompletion}
064         * when the handler is being executed concurrently.
065         * <p>Implementations may use the provided request and response but should
066         * avoid modifying them in ways that would conflict with the concurrent
067         * execution of the handler. A typical use of this method would be to
068         * clean up thread-local variables.
069         * @param request the current request
070         * @param response the current response
071         * @param handler the handler (or {@link HandlerMethod}) that started async
072         * execution, for type and/or instance examination
073         * @throws Exception in case of errors
074         */
075        default void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response,
076                        Object handler) throws Exception {
077        }
078
079}