/** * Process this request, publishing an event regardless of the outcome. * * <p>The actual event handling is performed by the abstract {@link #doService} template method. */ protected final void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { long startTime = System.currentTimeMillis(); Throwable failureCause = null; LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext(); LocaleContext localeContext = buildLocaleContext(request); RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes(); ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes); WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); asyncManager.registerCallableInterceptor( FrameworkServlet.class.getName(), new RequestBindingInterceptor()); initContextHolders(request, localeContext, requestAttributes); try { doService(request, response); } catch (ServletException ex) { failureCause = ex; throw ex; } catch (IOException ex) { failureCause = ex; throw ex; } catch (Throwable ex) { failureCause = ex; throw new NestedServletException("Request processing failed", ex); } finally { resetContextHolders(request, previousLocaleContext, previousAttributes); if (requestAttributes != null) { requestAttributes.requestCompleted(); } if (logger.isDebugEnabled()) { if (failureCause != null) { this.logger.debug("Could not complete request", failureCause); } else { if (asyncManager.isConcurrentHandlingStarted()) { logger.debug("Leaving response open for concurrent processing"); } else { this.logger.debug("Successfully completed request"); } } } publishRequestHandledEvent(request, response, startTime, failureCause); } }
@Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); TestCallableInterceptor callableInterceptor = new TestCallableInterceptor(); asyncManager.registerCallableInterceptor("mock-mvc", callableInterceptor); TestDeferredResultInterceptor deferredResultInterceptor = new TestDeferredResultInterceptor(); asyncManager.registerDeferredResultInterceptor("mock-mvc", deferredResultInterceptor); super.service(request, response); // TODO: add CountDownLatch to DeferredResultInterceptor and wait in request().asyncResult(..) Object handler = getMvcResult(request).getHandler(); if (asyncManager.isConcurrentHandlingStarted() && !deferredResultInterceptor.wasInvoked) { if (!callableInterceptor.await()) { throw new ServletException( "Gave up waiting on Callable from [" + handler.getClass().getName() + "] to complete"); } } }
@Override public boolean preHandle( HttpServletRequest request, final HttpServletResponse response, final Object handler) throws Exception { WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); asyncManager.setTimeoutHandler( new Runnable() { @Override public void run() { try { logger.debug("Custom time out handler called"); response.sendError( 503, "Async execution of [" + handler + "] did not complete on time"); } catch (IOException e) { logger.error("Timeout not handled", e); } } }); logger.debug("Registered custom timeout handler"); return true; }