Consistent result synchronization in WebAsyncManager
Issue: SPR-16571
This commit is contained in:
parent
58a5138f26
commit
cf74b1b8be
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2017 the original author or authors.
|
* Copyright 2002-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -51,6 +51,7 @@ import org.springframework.web.util.UrlPathHelper;
|
||||||
* detected via {@link #hasConcurrentResult()}.
|
* detected via {@link #hasConcurrentResult()}.
|
||||||
*
|
*
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
|
* @author Juergen Hoeller
|
||||||
* @since 3.2
|
* @since 3.2
|
||||||
* @see org.springframework.web.context.request.AsyncWebRequestInterceptor
|
* @see org.springframework.web.context.request.AsyncWebRequestInterceptor
|
||||||
* @see org.springframework.web.servlet.AsyncHandlerInterceptor
|
* @see org.springframework.web.servlet.AsyncHandlerInterceptor
|
||||||
|
@ -76,15 +77,13 @@ public final class WebAsyncManager {
|
||||||
|
|
||||||
private AsyncTaskExecutor taskExecutor = new SimpleAsyncTaskExecutor(this.getClass().getSimpleName());
|
private AsyncTaskExecutor taskExecutor = new SimpleAsyncTaskExecutor(this.getClass().getSimpleName());
|
||||||
|
|
||||||
private Object concurrentResult = RESULT_NONE;
|
private volatile Object concurrentResult = RESULT_NONE;
|
||||||
|
|
||||||
private Object[] concurrentResultContext;
|
private volatile Object[] concurrentResultContext;
|
||||||
|
|
||||||
private final Map<Object, CallableProcessingInterceptor> callableInterceptors =
|
private final Map<Object, CallableProcessingInterceptor> callableInterceptors = new LinkedHashMap<>();
|
||||||
new LinkedHashMap<>();
|
|
||||||
|
|
||||||
private final Map<Object, DeferredResultProcessingInterceptor> deferredResultInterceptors =
|
private final Map<Object, DeferredResultProcessingInterceptor> deferredResultInterceptors = new LinkedHashMap<>();
|
||||||
new LinkedHashMap<>();
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -105,7 +104,7 @@ public final class WebAsyncManager {
|
||||||
* {@code true}.
|
* {@code true}.
|
||||||
* @param asyncWebRequest the web request to use
|
* @param asyncWebRequest the web request to use
|
||||||
*/
|
*/
|
||||||
public void setAsyncWebRequest(final AsyncWebRequest asyncWebRequest) {
|
public void setAsyncWebRequest(AsyncWebRequest asyncWebRequest) {
|
||||||
Assert.notNull(asyncWebRequest, "AsyncWebRequest must not be null");
|
Assert.notNull(asyncWebRequest, "AsyncWebRequest must not be null");
|
||||||
this.asyncWebRequest = asyncWebRequest;
|
this.asyncWebRequest = asyncWebRequest;
|
||||||
this.asyncWebRequest.addCompletionHandler(() -> asyncWebRequest.removeAttribute(
|
this.asyncWebRequest.addCompletionHandler(() -> asyncWebRequest.removeAttribute(
|
||||||
|
@ -130,7 +129,7 @@ public final class WebAsyncManager {
|
||||||
* processing of the concurrent result.
|
* processing of the concurrent result.
|
||||||
*/
|
*/
|
||||||
public boolean isConcurrentHandlingStarted() {
|
public boolean isConcurrentHandlingStarted() {
|
||||||
return ((this.asyncWebRequest != null) && this.asyncWebRequest.isAsyncStarted());
|
return (this.asyncWebRequest != null && this.asyncWebRequest.isAsyncStarted());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -232,9 +231,11 @@ public final class WebAsyncManager {
|
||||||
* {@linkplain #getConcurrentResultContext() concurrentResultContext}.
|
* {@linkplain #getConcurrentResultContext() concurrentResultContext}.
|
||||||
*/
|
*/
|
||||||
public void clearConcurrentResult() {
|
public void clearConcurrentResult() {
|
||||||
|
synchronized (WebAsyncManager.this) {
|
||||||
this.concurrentResult = RESULT_NONE;
|
this.concurrentResult = RESULT_NONE;
|
||||||
this.concurrentResultContext = null;
|
this.concurrentResultContext = null;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start concurrent request processing and execute the given task with an
|
* Start concurrent request processing and execute the given task with an
|
||||||
|
@ -334,7 +335,7 @@ public final class WebAsyncManager {
|
||||||
|
|
||||||
private void setConcurrentResultAndDispatch(Object result) {
|
private void setConcurrentResultAndDispatch(Object result) {
|
||||||
synchronized (WebAsyncManager.this) {
|
synchronized (WebAsyncManager.this) {
|
||||||
if (hasConcurrentResult()) {
|
if (this.concurrentResult != RESULT_NONE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.concurrentResult = result;
|
this.concurrentResult = result;
|
||||||
|
@ -349,7 +350,6 @@ public final class WebAsyncManager {
|
||||||
logger.debug("Concurrent result value [" + this.concurrentResult +
|
logger.debug("Concurrent result value [" + this.concurrentResult +
|
||||||
"] - dispatching request to resume processing");
|
"] - dispatching request to resume processing");
|
||||||
}
|
}
|
||||||
|
|
||||||
this.asyncWebRequest.dispatch();
|
this.asyncWebRequest.dispatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -425,8 +425,10 @@ public final class WebAsyncManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startAsyncProcessing(Object[] processingContext) {
|
private void startAsyncProcessing(Object[] processingContext) {
|
||||||
clearConcurrentResult();
|
synchronized (WebAsyncManager.this) {
|
||||||
|
this.concurrentResult = RESULT_NONE;
|
||||||
this.concurrentResultContext = processingContext;
|
this.concurrentResultContext = processingContext;
|
||||||
|
}
|
||||||
this.asyncWebRequest.startAsync();
|
this.asyncWebRequest.startAsync();
|
||||||
|
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
|
|
Loading…
Reference in New Issue