Skip to content

Commit 65d47af

Browse files
committed
WebAsyncManager avoids concurrentResult.toString() and builds correct DeferredResultProcessingInterceptor keys
Issue: SPR-12253 (cherry picked from commit 901346e)
1 parent 2c92168 commit 65d47af

File tree

1 file changed

+28
-37
lines changed

1 file changed

+28
-37
lines changed

spring-web/src/main/java/org/springframework/web/context/request/async/WebAsyncManager.java

Lines changed: 28 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2013 the original author or authors.
2+
* Copyright 2002-2014 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -13,18 +13,19 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16+
1617
package org.springframework.web.context.request.async;
1718

1819
import java.util.ArrayList;
1920
import java.util.LinkedHashMap;
2021
import java.util.List;
2122
import java.util.Map;
2223
import java.util.concurrent.Callable;
23-
2424
import javax.servlet.http.HttpServletRequest;
2525

2626
import org.apache.commons.logging.Log;
2727
import org.apache.commons.logging.LogFactory;
28+
2829
import org.springframework.core.task.AsyncTaskExecutor;
2930
import org.springframework.core.task.SimpleAsyncTaskExecutor;
3031
import org.springframework.util.Assert;
@@ -48,7 +49,6 @@
4849
*
4950
* @author Rossen Stoyanchev
5051
* @since 3.2
51-
*
5252
* @see org.springframework.web.context.request.AsyncWebRequestInterceptor
5353
* @see org.springframework.web.servlet.AsyncHandlerInterceptor
5454
* @see org.springframework.web.filter.OncePerRequestFilter#shouldNotFilterAsyncDispatch
@@ -85,21 +85,21 @@ public final class WebAsyncManager {
8585

8686

8787
/**
88-
* Package private constructor.
88+
* Package-private constructor.
8989
* @see WebAsyncUtils#getAsyncManager(javax.servlet.ServletRequest)
9090
* @see WebAsyncUtils#getAsyncManager(org.springframework.web.context.request.WebRequest)
9191
*/
9292
WebAsyncManager() {
9393
}
9494

95+
9596
/**
9697
* Configure the {@link AsyncWebRequest} to use. This property may be set
9798
* more than once during a single request to accurately reflect the current
9899
* state of the request (e.g. following a forward, request/response
99100
* wrapping, etc). However, it should not be set while concurrent handling
100101
* is in progress, i.e. while {@link #isConcurrentHandlingStarted()} is
101102
* {@code true}.
102-
*
103103
* @param asyncWebRequest the web request to use
104104
*/
105105
public void setAsyncWebRequest(final AsyncWebRequest asyncWebRequest) {
@@ -143,7 +143,6 @@ public boolean hasConcurrentResult() {
143143

144144
/**
145145
* Provides access to the result from concurrent handling.
146-
*
147146
* @return an Object, possibly an {@code Exception} or {@code Throwable} if
148147
* concurrent handling raised one.
149148
* @see #clearConcurrentResult()
@@ -155,7 +154,6 @@ public Object getConcurrentResult() {
155154
/**
156155
* Provides access to additional processing context saved at the start of
157156
* concurrent handling.
158-
*
159157
* @see #clearConcurrentResult()
160158
*/
161159
public Object[] getConcurrentResultContext() {
@@ -216,14 +214,14 @@ public void registerDeferredResultInterceptor(Object key, DeferredResultProcessi
216214
}
217215

218216
/**
219-
* Register a {@link DeferredResultProcessingInterceptor} without a key.
220-
* The key is derived from the class name and hashcode.
217+
* Register one or more {@link DeferredResultProcessingInterceptor}s without a specified key.
218+
* The default key is derived from the interceptor class name and hash code.
221219
* @param interceptors one or more interceptors to register
222220
*/
223221
public void registerDeferredResultInterceptors(DeferredResultProcessingInterceptor... interceptors) {
224222
Assert.notNull(interceptors, "A DeferredResultProcessingInterceptor is required");
225223
for (DeferredResultProcessingInterceptor interceptor : interceptors) {
226-
String key = interceptors.getClass().getName() + ":" + interceptors.hashCode();
224+
String key = interceptor.getClass().getName() + ":" + interceptor.hashCode();
227225
this.deferredResultInterceptors.put(key, interceptor);
228226
}
229227
}
@@ -243,17 +241,15 @@ public void clearConcurrentResult() {
243241
* from the task execution is saved and the request dispatched in order to
244242
* resume processing of that result. If the task raises an Exception then
245243
* the saved result will be the raised Exception.
246-
*
247244
* @param callable a unit of work to be executed asynchronously
248245
* @param processingContext additional context to save that can be accessed
249246
* via {@link #getConcurrentResultContext()}
250-
* @throws Exception If concurrent processing failed to start
251-
*
247+
* @throws Exception if concurrent processing failed to start
252248
* @see #getConcurrentResult()
253249
* @see #getConcurrentResultContext()
254250
*/
255-
@SuppressWarnings({"unchecked" })
256-
public void startCallableProcessing(final Callable<?> callable, Object... processingContext) throws Exception {
251+
@SuppressWarnings({"unchecked", "rawtypes"})
252+
public void startCallableProcessing(Callable<?> callable, Object... processingContext) throws Exception {
257253
Assert.notNull(callable, "Callable must not be null");
258254
startCallableProcessing(new WebAsyncTask(callable), processingContext);
259255
}
@@ -262,11 +258,10 @@ public void startCallableProcessing(final Callable<?> callable, Object... proces
262258
* Use the given {@link WebAsyncTask} to configure the task executor as well as
263259
* the timeout value of the {@code AsyncWebRequest} before delegating to
264260
* {@link #startCallableProcessing(Callable, Object...)}.
265-
*
266261
* @param webAsyncTask a WebAsyncTask containing the target {@code Callable}
267262
* @param processingContext additional context to save that can be accessed
268263
* via {@link #getConcurrentResultContext()}
269-
* @throws Exception If concurrent processing failed to start
264+
* @throws Exception if concurrent processing failed to start
270265
*/
271266
public void startCallableProcessing(final WebAsyncTask<?> webAsyncTask, Object... processingContext) throws Exception {
272267
Assert.notNull(webAsyncTask, "WebAsyncTask must not be null");
@@ -306,8 +301,7 @@ public void run() {
306301
}
307302
});
308303

309-
interceptorChain.applyBeforeConcurrentHandling(asyncWebRequest, callable);
310-
304+
interceptorChain.applyBeforeConcurrentHandling(this.asyncWebRequest, callable);
311305
startAsyncProcessing(processingContext);
312306

313307
this.taskExecutor.submit(new Runnable() {
@@ -317,8 +311,8 @@ public void run() {
317311
interceptorChain.applyPreProcess(asyncWebRequest, callable);
318312
result = callable.call();
319313
}
320-
catch (Throwable t) {
321-
result = t;
314+
catch (Throwable ex) {
315+
result = ex;
322316
}
323317
finally {
324318
result = interceptorChain.applyPostProcess(asyncWebRequest, callable, result);
@@ -333,18 +327,20 @@ private void setConcurrentResultAndDispatch(Object result) {
333327
if (hasConcurrentResult()) {
334328
return;
335329
}
336-
concurrentResult = result;
330+
this.concurrentResult = result;
337331
}
338332

339-
if (asyncWebRequest.isAsyncComplete()) {
333+
if (this.asyncWebRequest.isAsyncComplete()) {
340334
logger.error("Could not complete async processing due to timeout or network error");
341335
return;
342336
}
343337

344-
logger.debug("Concurrent result value [" + concurrentResult + "]");
345-
logger.debug("Dispatching request to resume processing");
338+
if (logger.isDebugEnabled()) {
339+
logger.debug("Concurrent result value [" + this.concurrentResult +
340+
"] - dispatching request to resume processing");
341+
}
346342

347-
asyncWebRequest.dispatch();
343+
this.asyncWebRequest.dispatch();
348344
}
349345

350346
/**
@@ -354,12 +350,10 @@ private void setConcurrentResultAndDispatch(Object result) {
354350
* result. The {@code AsyncWebRequest} is also updated with a completion
355351
* handler that expires the {@code DeferredResult} and a timeout handler
356352
* assuming the {@code DeferredResult} has a default timeout result.
357-
*
358353
* @param deferredResult the DeferredResult instance to initialize
359354
* @param processingContext additional context to save that can be accessed
360355
* via {@link #getConcurrentResultContext()}
361-
* @throws Exception If concurrent processing failed to start
362-
*
356+
* @throws Exception if concurrent processing failed to start
363357
* @see #getConcurrentResult()
364358
* @see #getConcurrentResultContext()
365359
*/
@@ -386,8 +380,8 @@ public void run() {
386380
try {
387381
interceptorChain.triggerAfterTimeout(asyncWebRequest, deferredResult);
388382
}
389-
catch (Throwable t) {
390-
setConcurrentResultAndDispatch(t);
383+
catch (Throwable ex) {
384+
setConcurrentResultAndDispatch(ex);
391385
}
392386
}
393387
});
@@ -398,8 +392,7 @@ public void run() {
398392
}
399393
});
400394

401-
interceptorChain.applyBeforeConcurrentHandling(asyncWebRequest, deferredResult);
402-
395+
interceptorChain.applyBeforeConcurrentHandling(this.asyncWebRequest, deferredResult);
403396
startAsyncProcessing(processingContext);
404397

405398
try {
@@ -411,16 +404,14 @@ public void handleResult(Object result) {
411404
}
412405
});
413406
}
414-
catch (Throwable t) {
415-
setConcurrentResultAndDispatch(t);
407+
catch (Throwable ex) {
408+
setConcurrentResultAndDispatch(ex);
416409
}
417410
}
418411

419412
private void startAsyncProcessing(Object[] processingContext) {
420-
421413
clearConcurrentResult();
422414
this.concurrentResultContext = processingContext;
423-
424415
this.asyncWebRequest.startAsync();
425416

426417
if (logger.isDebugEnabled()) {

0 commit comments

Comments
 (0)