WebAsyncManager avoids concurrentResult.toString() and builds correct DeferredResultProcessingInterceptor keys
Issue: SPR-12253
(cherry picked from commit bf99d6a)
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.web.context.request.async;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -20,11 +21,11 @@ import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.core.task.AsyncTaskExecutor;
|
||||
import org.springframework.core.task.SimpleAsyncTaskExecutor;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -48,7 +49,6 @@ import org.springframework.web.util.UrlPathHelper;
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 3.2
|
||||
*
|
||||
* @see org.springframework.web.context.request.AsyncWebRequestInterceptor
|
||||
* @see org.springframework.web.servlet.AsyncHandlerInterceptor
|
||||
* @see org.springframework.web.filter.OncePerRequestFilter#shouldNotFilterAsyncDispatch
|
||||
@@ -85,13 +85,14 @@ public final class WebAsyncManager {
|
||||
|
||||
|
||||
/**
|
||||
* Package private constructor.
|
||||
* Package-private constructor.
|
||||
* @see WebAsyncUtils#getAsyncManager(javax.servlet.ServletRequest)
|
||||
* @see WebAsyncUtils#getAsyncManager(org.springframework.web.context.request.WebRequest)
|
||||
*/
|
||||
WebAsyncManager() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Configure the {@link AsyncWebRequest} to use. This property may be set
|
||||
* more than once during a single request to accurately reflect the current
|
||||
@@ -99,7 +100,6 @@ public final class WebAsyncManager {
|
||||
* wrapping, etc). However, it should not be set while concurrent handling
|
||||
* is in progress, i.e. while {@link #isConcurrentHandlingStarted()} is
|
||||
* {@code true}.
|
||||
*
|
||||
* @param asyncWebRequest the web request to use
|
||||
*/
|
||||
public void setAsyncWebRequest(final AsyncWebRequest asyncWebRequest) {
|
||||
@@ -144,7 +144,6 @@ public final class WebAsyncManager {
|
||||
|
||||
/**
|
||||
* Provides access to the result from concurrent handling.
|
||||
*
|
||||
* @return an Object, possibly an {@code Exception} or {@code Throwable} if
|
||||
* concurrent handling raised one.
|
||||
* @see #clearConcurrentResult()
|
||||
@@ -156,7 +155,6 @@ public final class WebAsyncManager {
|
||||
/**
|
||||
* Provides access to additional processing context saved at the start of
|
||||
* concurrent handling.
|
||||
*
|
||||
* @see #clearConcurrentResult()
|
||||
*/
|
||||
public Object[] getConcurrentResultContext() {
|
||||
@@ -217,14 +215,14 @@ public final class WebAsyncManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a {@link DeferredResultProcessingInterceptor} without a key.
|
||||
* The key is derived from the class name and hashcode.
|
||||
* Register one or more {@link DeferredResultProcessingInterceptor}s without a specified key.
|
||||
* The default key is derived from the interceptor class name and hash code.
|
||||
* @param interceptors one or more interceptors to register
|
||||
*/
|
||||
public void registerDeferredResultInterceptors(DeferredResultProcessingInterceptor... interceptors) {
|
||||
Assert.notNull(interceptors, "A DeferredResultProcessingInterceptor is required");
|
||||
for (DeferredResultProcessingInterceptor interceptor : interceptors) {
|
||||
String key = interceptors.getClass().getName() + ":" + interceptors.hashCode();
|
||||
String key = interceptor.getClass().getName() + ":" + interceptor.hashCode();
|
||||
this.deferredResultInterceptors.put(key, interceptor);
|
||||
}
|
||||
}
|
||||
@@ -244,12 +242,10 @@ public final class WebAsyncManager {
|
||||
* from the task execution is saved and the request dispatched in order to
|
||||
* resume processing of that result. If the task raises an Exception then
|
||||
* the saved result will be the raised Exception.
|
||||
*
|
||||
* @param callable a unit of work to be executed asynchronously
|
||||
* @param processingContext additional context to save that can be accessed
|
||||
* via {@link #getConcurrentResultContext()}
|
||||
* @throws Exception If concurrent processing failed to start
|
||||
*
|
||||
* @throws Exception if concurrent processing failed to start
|
||||
* @see #getConcurrentResult()
|
||||
* @see #getConcurrentResultContext()
|
||||
*/
|
||||
@@ -263,11 +259,10 @@ public final class WebAsyncManager {
|
||||
* Use the given {@link WebAsyncTask} to configure the task executor as well as
|
||||
* the timeout value of the {@code AsyncWebRequest} before delegating to
|
||||
* {@link #startCallableProcessing(Callable, Object...)}.
|
||||
*
|
||||
* @param webAsyncTask a WebAsyncTask containing the target {@code Callable}
|
||||
* @param processingContext additional context to save that can be accessed
|
||||
* via {@link #getConcurrentResultContext()}
|
||||
* @throws Exception If concurrent processing failed to start
|
||||
* @throws Exception if concurrent processing failed to start
|
||||
*/
|
||||
public void startCallableProcessing(final WebAsyncTask<?> webAsyncTask, Object... processingContext) throws Exception {
|
||||
Assert.notNull(webAsyncTask, "WebAsyncTask must not be null");
|
||||
@@ -309,8 +304,7 @@ public final class WebAsyncManager {
|
||||
}
|
||||
});
|
||||
|
||||
interceptorChain.applyBeforeConcurrentHandling(asyncWebRequest, callable);
|
||||
|
||||
interceptorChain.applyBeforeConcurrentHandling(this.asyncWebRequest, callable);
|
||||
startAsyncProcessing(processingContext);
|
||||
|
||||
this.taskExecutor.submit(new Runnable() {
|
||||
@@ -321,8 +315,8 @@ public final class WebAsyncManager {
|
||||
interceptorChain.applyPreProcess(asyncWebRequest, callable);
|
||||
result = callable.call();
|
||||
}
|
||||
catch (Throwable t) {
|
||||
result = t;
|
||||
catch (Throwable ex) {
|
||||
result = ex;
|
||||
}
|
||||
finally {
|
||||
result = interceptorChain.applyPostProcess(asyncWebRequest, callable, result);
|
||||
@@ -337,18 +331,20 @@ public final class WebAsyncManager {
|
||||
if (hasConcurrentResult()) {
|
||||
return;
|
||||
}
|
||||
concurrentResult = result;
|
||||
this.concurrentResult = result;
|
||||
}
|
||||
|
||||
if (asyncWebRequest.isAsyncComplete()) {
|
||||
if (this.asyncWebRequest.isAsyncComplete()) {
|
||||
logger.error("Could not complete async processing due to timeout or network error");
|
||||
return;
|
||||
}
|
||||
|
||||
logger.debug("Concurrent result value [" + concurrentResult + "]");
|
||||
logger.debug("Dispatching request to resume processing");
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Concurrent result value [" + this.concurrentResult +
|
||||
"] - dispatching request to resume processing");
|
||||
}
|
||||
|
||||
asyncWebRequest.dispatch();
|
||||
this.asyncWebRequest.dispatch();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -358,12 +354,10 @@ public final class WebAsyncManager {
|
||||
* result. The {@code AsyncWebRequest} is also updated with a completion
|
||||
* handler that expires the {@code DeferredResult} and a timeout handler
|
||||
* assuming the {@code DeferredResult} has a default timeout result.
|
||||
*
|
||||
* @param deferredResult the DeferredResult instance to initialize
|
||||
* @param processingContext additional context to save that can be accessed
|
||||
* via {@link #getConcurrentResultContext()}
|
||||
* @throws Exception If concurrent processing failed to start
|
||||
*
|
||||
* @throws Exception if concurrent processing failed to start
|
||||
* @see #getConcurrentResult()
|
||||
* @see #getConcurrentResultContext()
|
||||
*/
|
||||
@@ -391,8 +385,8 @@ public final class WebAsyncManager {
|
||||
try {
|
||||
interceptorChain.triggerAfterTimeout(asyncWebRequest, deferredResult);
|
||||
}
|
||||
catch (Throwable t) {
|
||||
setConcurrentResultAndDispatch(t);
|
||||
catch (Throwable ex) {
|
||||
setConcurrentResultAndDispatch(ex);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -404,8 +398,7 @@ public final class WebAsyncManager {
|
||||
}
|
||||
});
|
||||
|
||||
interceptorChain.applyBeforeConcurrentHandling(asyncWebRequest, deferredResult);
|
||||
|
||||
interceptorChain.applyBeforeConcurrentHandling(this.asyncWebRequest, deferredResult);
|
||||
startAsyncProcessing(processingContext);
|
||||
|
||||
try {
|
||||
@@ -418,16 +411,14 @@ public final class WebAsyncManager {
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Throwable t) {
|
||||
setConcurrentResultAndDispatch(t);
|
||||
catch (Throwable ex) {
|
||||
setConcurrentResultAndDispatch(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void startAsyncProcessing(Object[] processingContext) {
|
||||
|
||||
clearConcurrentResult();
|
||||
this.concurrentResultContext = processingContext;
|
||||
|
||||
this.asyncWebRequest.startAsync();
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
|
||||
Reference in New Issue
Block a user