001/* 002 * Copyright 2002-2019 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.config.annotation; 018 019import java.util.ArrayList; 020import java.util.Arrays; 021import java.util.List; 022import java.util.concurrent.Callable; 023 024import org.springframework.core.task.AsyncTaskExecutor; 025import org.springframework.core.task.SimpleAsyncTaskExecutor; 026import org.springframework.lang.Nullable; 027import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; 028import org.springframework.web.context.request.async.CallableProcessingInterceptor; 029import org.springframework.web.context.request.async.DeferredResult; 030import org.springframework.web.context.request.async.DeferredResultProcessingInterceptor; 031 032/** 033 * Helps with configuring options for asynchronous request processing. 034 * 035 * @author Rossen Stoyanchev 036 * @since 3.2 037 */ 038public class AsyncSupportConfigurer { 039 040 @Nullable 041 private AsyncTaskExecutor taskExecutor; 042 043 @Nullable 044 private Long timeout; 045 046 private final List<CallableProcessingInterceptor> callableInterceptors = new ArrayList<>(); 047 048 private final List<DeferredResultProcessingInterceptor> deferredResultInterceptors = new ArrayList<>(); 049 050 051 /** 052 * The provided task executor is used to: 053 * <ol> 054 * <li>Handle {@link Callable} controller method return values. 055 * <li>Perform blocking writes when streaming to the response 056 * through a reactive (e.g. Reactor, RxJava) controller method return value. 057 * </ol> 058 * <p>By default only a {@link SimpleAsyncTaskExecutor} is used. However when 059 * using the above two use cases, it's recommended to configure an executor 060 * backed by a thread pool such as {@link ThreadPoolTaskExecutor}. 061 * @param taskExecutor the task executor instance to use by default 062 */ 063 public AsyncSupportConfigurer setTaskExecutor(AsyncTaskExecutor taskExecutor) { 064 this.taskExecutor = taskExecutor; 065 return this; 066 } 067 068 /** 069 * Specify the amount of time, in milliseconds, before asynchronous request 070 * handling times out. In Servlet 3, the timeout begins after the main request 071 * processing thread has exited and ends when the request is dispatched again 072 * for further processing of the concurrently produced result. 073 * <p>If this value is not set, the default timeout of the underlying 074 * implementation is used. 075 * @param timeout the timeout value in milliseconds 076 */ 077 public AsyncSupportConfigurer setDefaultTimeout(long timeout) { 078 this.timeout = timeout; 079 return this; 080 } 081 082 /** 083 * Configure lifecycle interceptors with callbacks around concurrent request 084 * execution that starts when a controller returns a 085 * {@link java.util.concurrent.Callable}. 086 * @param interceptors the interceptors to register 087 */ 088 public AsyncSupportConfigurer registerCallableInterceptors(CallableProcessingInterceptor... interceptors) { 089 this.callableInterceptors.addAll(Arrays.asList(interceptors)); 090 return this; 091 } 092 093 /** 094 * Configure lifecycle interceptors with callbacks around concurrent request 095 * execution that starts when a controller returns a {@link DeferredResult}. 096 * @param interceptors the interceptors to register 097 */ 098 public AsyncSupportConfigurer registerDeferredResultInterceptors( 099 DeferredResultProcessingInterceptor... interceptors) { 100 101 this.deferredResultInterceptors.addAll(Arrays.asList(interceptors)); 102 return this; 103 } 104 105 106 @Nullable 107 protected AsyncTaskExecutor getTaskExecutor() { 108 return this.taskExecutor; 109 } 110 111 @Nullable 112 protected Long getTimeout() { 113 return this.timeout; 114 } 115 116 protected List<CallableProcessingInterceptor> getCallableInterceptors() { 117 return this.callableInterceptors; 118 } 119 120 protected List<DeferredResultProcessingInterceptor> getDeferredResultInterceptors() { 121 return this.deferredResultInterceptors; 122 } 123 124}