|
|
|
|
@ -26,23 +26,21 @@ import org.springframework.util.Assert;
@@ -26,23 +26,21 @@ import org.springframework.util.Assert;
|
|
|
|
|
import org.springframework.web.context.request.NativeWebRequest; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* {@code DeferredResult} provides an alternative to using a {@link Callable} |
|
|
|
|
* for asynchronous request processing. While a {@code Callable} is executed |
|
|
|
|
* concurrently on behalf of the application, with a {@code DeferredResult} the |
|
|
|
|
* application can produce the result from a thread of its choice. |
|
|
|
|
* {@code DeferredResult} provides an alternative to using a {@link Callable} for |
|
|
|
|
* asynchronous request processing. While a {@code Callable} is executed concurrently |
|
|
|
|
* on behalf of the application, with a {@code DeferredResult} the application can |
|
|
|
|
* produce the result from a thread of its choice. |
|
|
|
|
* |
|
|
|
|
* <p>Subclasses can extend this class to easily associate additional data or |
|
|
|
|
* behavior with the {@link DeferredResult}. For example, one might want to |
|
|
|
|
* associate the user used to create the {@link DeferredResult} by extending the |
|
|
|
|
* class and adding an additional property for the user. In this way, the user |
|
|
|
|
* could easily be accessed later without the need to use a data structure to do |
|
|
|
|
* the mapping. |
|
|
|
|
* <p>Subclasses can extend this class to easily associate additional data or behavior |
|
|
|
|
* with the {@link DeferredResult}. For example, one might want to associate the user |
|
|
|
|
* used to create the {@link DeferredResult} by extending the class and adding an |
|
|
|
|
* additional property for the user. In this way, the user could easily be accessed |
|
|
|
|
* later without the need to use a data structure to do the mapping. |
|
|
|
|
* |
|
|
|
|
* <p>An example of associating additional behavior to this class might be |
|
|
|
|
* realized by extending the class to implement an additional interface. For |
|
|
|
|
* example, one might want to implement {@link Comparable} so that when the |
|
|
|
|
* {@link DeferredResult} is added to a {@link PriorityQueue} it is handled in |
|
|
|
|
* the correct order. |
|
|
|
|
* <p>An example of associating additional behavior to this class might be realized |
|
|
|
|
* by extending the class to implement an additional interface. For example, one |
|
|
|
|
* might want to implement {@link Comparable} so that when the {@link DeferredResult} |
|
|
|
|
* is added to a {@link PriorityQueue} it is handled in the correct order. |
|
|
|
|
* |
|
|
|
|
* @author Rossen Stoyanchev |
|
|
|
|
* @author Rob Winch |
|
|
|
|
@ -50,10 +48,10 @@ import org.springframework.web.context.request.NativeWebRequest;
@@ -50,10 +48,10 @@ import org.springframework.web.context.request.NativeWebRequest;
|
|
|
|
|
*/ |
|
|
|
|
public class DeferredResult<T> { |
|
|
|
|
|
|
|
|
|
private static final Log logger = LogFactory.getLog(DeferredResult.class); |
|
|
|
|
|
|
|
|
|
private static final Object RESULT_NONE = new Object(); |
|
|
|
|
|
|
|
|
|
private static final Log logger = LogFactory.getLog(DeferredResult.class); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private final Long timeout; |
|
|
|
|
|
|
|
|
|
@ -88,7 +86,7 @@ public class DeferredResult<T> {
@@ -88,7 +86,7 @@ public class DeferredResult<T> {
|
|
|
|
|
/** |
|
|
|
|
* Create a DeferredResult with a timeout value and a default result to use |
|
|
|
|
* in case of timeout. |
|
|
|
|
* @param timeout timeout value in milliseconds; ignored if {@code null} |
|
|
|
|
* @param timeout timeout value in milliseconds (ignored if {@code null}) |
|
|
|
|
* @param timeoutResult the result to use |
|
|
|
|
*/ |
|
|
|
|
public DeferredResult(Long timeout, Object timeoutResult) { |
|
|
|
|
@ -111,6 +109,7 @@ public class DeferredResult<T> {
@@ -111,6 +109,7 @@ public class DeferredResult<T> {
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Return {@code true} if the DeferredResult has been set. |
|
|
|
|
* @since 4.0 |
|
|
|
|
*/ |
|
|
|
|
public boolean hasResult() { |
|
|
|
|
return (this.result != RESULT_NONE); |
|
|
|
|
@ -120,6 +119,7 @@ public class DeferredResult<T> {
@@ -120,6 +119,7 @@ public class DeferredResult<T> {
|
|
|
|
|
* Return the result, or {@code null} if the result wasn't set. Since the result |
|
|
|
|
* can also be {@code null}, it is recommended to use {@link #hasResult()} first |
|
|
|
|
* to check if there is a result prior to calling this method. |
|
|
|
|
* @since 4.0 |
|
|
|
|
*/ |
|
|
|
|
public Object getResult() { |
|
|
|
|
Object resultToCheck = this.result; |
|
|
|
|
@ -134,22 +134,21 @@ public class DeferredResult<T> {
@@ -134,22 +134,21 @@ public class DeferredResult<T> {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Register code to invoke when the async request times out. This method is |
|
|
|
|
* called from a container thread when an async request times out before the |
|
|
|
|
* {@code DeferredResult} has been set. It may invoke |
|
|
|
|
* {@link DeferredResult#setResult(Object) setResult} or |
|
|
|
|
* {@link DeferredResult#setErrorResult(Object) setErrorResult} to resume |
|
|
|
|
* processing. |
|
|
|
|
* Register code to invoke when the async request times out. |
|
|
|
|
* <p>This method is called from a container thread when an async request |
|
|
|
|
* times out before the {@code DeferredResult} has been populated. |
|
|
|
|
* It may invoke {@link DeferredResult#setResult setResult} or |
|
|
|
|
* {@link DeferredResult#setErrorResult setErrorResult} to resume processing. |
|
|
|
|
*/ |
|
|
|
|
public void onTimeout(Runnable callback) { |
|
|
|
|
this.timeoutCallback = callback; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Register code to invoke when the async request completes. This method is |
|
|
|
|
* called from a container thread when an async request completed for any |
|
|
|
|
* reason including timeout and network error. This method is useful for |
|
|
|
|
* detecting that a {@code DeferredResult} instance is no longer usable. |
|
|
|
|
* Register code to invoke when the async request completes. |
|
|
|
|
* <p>This method is called from a container thread when an async request |
|
|
|
|
* completed for any reason including timeout and network error. This is useful |
|
|
|
|
* for detecting that a {@code DeferredResult} instance is no longer usable. |
|
|
|
|
*/ |
|
|
|
|
public void onCompletion(Runnable callback) { |
|
|
|
|
this.completionCallback = callback; |
|
|
|
|
@ -178,8 +177,8 @@ public class DeferredResult<T> {
@@ -178,8 +177,8 @@ public class DeferredResult<T> {
|
|
|
|
|
/** |
|
|
|
|
* Set the value for the DeferredResult and handle it. |
|
|
|
|
* @param result the value to set |
|
|
|
|
* @return "true" if the result was set and passed on for handling; "false" |
|
|
|
|
* if the result was already set or the async request expired. |
|
|
|
|
* @return "true" if the result was set and passed on for handling; |
|
|
|
|
* "false" if the result was already set or the async request expired |
|
|
|
|
* @see #isSetOrExpired() |
|
|
|
|
*/ |
|
|
|
|
public boolean setResult(T result) { |
|
|
|
|
@ -200,13 +199,12 @@ public class DeferredResult<T> {
@@ -200,13 +199,12 @@ public class DeferredResult<T> {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Set an error value for the {@link DeferredResult} and handle it. The value |
|
|
|
|
* may be an {@link Exception} or {@link Throwable} in which case it will be |
|
|
|
|
* processed as if a handler raised the exception. |
|
|
|
|
* Set an error value for the {@link DeferredResult} and handle it. |
|
|
|
|
* The value may be an {@link Exception} or {@link Throwable} in which case |
|
|
|
|
* it will be processed as if a handler raised the exception. |
|
|
|
|
* @param result the error result value |
|
|
|
|
* @return "true" if the result was set to the error value and passed on for |
|
|
|
|
* handling; "false" if the result was already set or the async request |
|
|
|
|
* expired. |
|
|
|
|
* handling; "false" if the result was already set or the async request expired |
|
|
|
|
* @see #isSetOrExpired() |
|
|
|
|
*/ |
|
|
|
|
public boolean setErrorResult(Object result) { |
|
|
|
|
|