1 /* 2 * Copyright 2002-2012 the original author or authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package org.springframework.web.context.request.async; 17 18 import java.util.concurrent.Callable; 19 20 import org.springframework.core.task.AsyncTaskExecutor; 21 import org.springframework.web.context.request.NativeWebRequest; 22 23 /** 24 * Intercepts concurrent request handling, where the concurrent result is 25 * obtained by executing a {@link Callable} on behalf of the application with 26 * an {@link AsyncTaskExecutor}. 27 * 28 * <p>A {@code CallableProcessingInterceptor} is invoked before and after the 29 * invocation of the {@code Callable} task in the asynchronous thread, as well 30 * as on timeout from a container thread, or after completing for any reason 31 * including a timeout or network error. 32 * 33 * <p>As a general rule exceptions raised by interceptor methods will cause 34 * async processing to resume by dispatching back to the container and using 35 * the Exception instance as the concurrent result. Such exceptions will then 36 * be processed through the {@code HandlerExceptionResolver} mechanism. 37 * 38 * <p>The {@link #handleTimeout(NativeWebRequest, Callable) afterTimeout} method 39 * can select a value to be used to resume processing. 40 * 41 * @author Rossen Stoyanchev 42 * @author Rob Winch 43 * @since 3.2 44 */ 45 public interface CallableProcessingInterceptor { 46 47 static final Object RESULT_NONE = new Object(); 48 49 static final Object RESPONSE_HANDLED = new Object(); 50 51 /** 52 * Invoked <em>before</em> the start of concurrent handling in the original 53 * thread in which the {@code Callable} is submitted for concurrent handling. 54 * 55 * <p> 56 * This is useful for capturing the state of the current thread just prior to 57 * invoking the {@link Callable}. Once the state is captured, it can then be 58 * transferred to the new {@link Thread} in 59 * {@link #preProcess(NativeWebRequest, Callable)}. Capturing the state of 60 * Spring Security's SecurityContextHolder and migrating it to the new Thread 61 * is a concrete example of where this is useful. 62 * </p> 63 * 64 * @param request the current request 65 * @param task the task for the current async request 66 * @throws Exception in case of errors 67 */ 68 <T> void beforeConcurrentHandling(NativeWebRequest request, Callable<T> task) throws Exception; 69 70 /** 71 * Invoked <em>after</em> the start of concurrent handling in the async 72 * thread in which the {@code Callable} is executed and <em>before</em> the 73 * actual invocation of the {@code Callable}. 74 * 75 * @param request the current request 76 * @param task the task for the current async request 77 * @throws Exception in case of errors 78 */ 79 <T> void preProcess(NativeWebRequest request, Callable<T> task) throws Exception; 80 81 /** 82 * Invoked <em>after</em> the {@code Callable} has produced a result in the 83 * async thread in which the {@code Callable} is executed. This method may 84 * be invoked later than {@code afterTimeout} or {@code afterCompletion} 85 * depending on when the {@code Callable} finishes processing. 86 * 87 * @param request the current request 88 * @param task the task for the current async request 89 * @param concurrentResult the result of concurrent processing, which could 90 * be a {@link Throwable} if the {@code Callable} raised an exception 91 * @throws Exception in case of errors 92 */ 93 <T> void postProcess(NativeWebRequest request, Callable<T> task, Object concurrentResult) throws Exception; 94 95 /** 96 * Invoked from a container thread when the async request times out before 97 * the {@code Callable} task completes. Implementations may return a value, 98 * including an {@link Exception}, to use instead of the value the 99 * {@link Callable} did not return in time. 100 * 101 * @param request the current request 102 * @param task the task for the current async request 103 * @return a concurrent result value; if the value is anything other than 104 * {@link #RESULT_NONE} or {@link #RESPONSE_HANDLED}, concurrent processing 105 * is resumed and subsequent interceptors are not invoked 106 * @throws Exception in case of errors 107 */ 108 <T> Object handleTimeout(NativeWebRequest request, Callable<T> task) throws Exception; 109 110 /** 111 * Invoked from a container thread when async processing completes for any 112 * reason including timeout or network error. 113 * 114 * @param request the current request 115 * @param task the task for the current async request 116 * @throws Exception in case of errors 117 */ 118 <T> void afterCompletion(NativeWebRequest request, Callable<T> task) throws Exception; 119 120 }