Issue
When I am using custom HandlerInterceptor
and my controller returns DeferredResult
, the preHandle
method of my custom interceptor called twice on each request. Consider a toy example.
My custom interceptor:
public class MyInterceptor implements HandlerInterceptor {
static int i = 0;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println(i++);
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
My Spring Java configuration:
@Configuration
@EnableWebMvc
public class ApplicationConfiguration extends WebMvcConfigurerAdapter {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor());
}
}
My Controller:
@Controller
public class MyController {
@RequestMapping(value = "/test", method = RequestMethod.GET)
public DeferredResult<String> test() {
DeferredResult<String> df = new DeferredResult<String>();
df.setResult("blank");
return df;
}
}
So, on each page load I see two outputs from preHandle
method. However, if I modify MyController
in order to return just "blank" template (instead of DeferredResult
with "blank" template), I see just one output from preHandle
on each page load.
So, my question is why preHandle
called twice when I use DeferredResult
and is it possible to avoid this?
Solution
You need to use org.springframework.web.servlet.AsyncHandlerInterceptor
:
public interface AsyncHandlerInterceptor extends HandlerInterceptor {
void afterConcurrentHandlingStarted(
HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception;
}
Spring MVC execute sequence:
preHandle
afterConcurrentHandlingStarted
preHandle
postHandle
afterCompletion
Answered By - Vadim Kolesnikov