ListenableFuture provides CompletableFuture adaptation via completable()
Issue: SPR-15696
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.scheduling.annotation;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@@ -48,7 +49,7 @@ public class AsyncResult<V> implements ListenableFuture<V> {
|
||||
|
||||
private final V value;
|
||||
|
||||
private final ExecutionException executionException;
|
||||
private final Throwable executionException;
|
||||
|
||||
|
||||
/**
|
||||
@@ -63,7 +64,7 @@ public class AsyncResult<V> implements ListenableFuture<V> {
|
||||
* Create a new AsyncResult holder.
|
||||
* @param value the value to pass through
|
||||
*/
|
||||
private AsyncResult(@Nullable V value, @Nullable ExecutionException ex) {
|
||||
private AsyncResult(@Nullable V value, @Nullable Throwable ex) {
|
||||
this.value = value;
|
||||
this.executionException = ex;
|
||||
}
|
||||
@@ -87,7 +88,9 @@ public class AsyncResult<V> implements ListenableFuture<V> {
|
||||
@Override
|
||||
public V get() throws ExecutionException {
|
||||
if (this.executionException != null) {
|
||||
throw this.executionException;
|
||||
throw (this.executionException instanceof ExecutionException ?
|
||||
(ExecutionException) this.executionException :
|
||||
new ExecutionException(this.executionException));
|
||||
}
|
||||
return this.value;
|
||||
}
|
||||
@@ -106,8 +109,7 @@ public class AsyncResult<V> implements ListenableFuture<V> {
|
||||
public void addCallback(SuccessCallback<? super V> successCallback, FailureCallback failureCallback) {
|
||||
try {
|
||||
if (this.executionException != null) {
|
||||
Throwable cause = this.executionException.getCause();
|
||||
failureCallback.onFailure(cause != null ? cause : this.executionException);
|
||||
failureCallback.onFailure(exposedException(this.executionException));
|
||||
}
|
||||
else {
|
||||
successCallback.onSuccess(this.value);
|
||||
@@ -118,6 +120,18 @@ public class AsyncResult<V> implements ListenableFuture<V> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<V> completable() {
|
||||
if (this.executionException != null) {
|
||||
CompletableFuture<V> completable = new CompletableFuture<>();
|
||||
completable.completeExceptionally(exposedException(this.executionException));
|
||||
return completable;
|
||||
}
|
||||
else {
|
||||
return CompletableFuture.completedFuture(this.value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a new async result which exposes the given value from {@link Future#get()}.
|
||||
@@ -138,8 +152,23 @@ public class AsyncResult<V> implements ListenableFuture<V> {
|
||||
* @see ExecutionException
|
||||
*/
|
||||
public static <V> ListenableFuture<V> forExecutionException(Throwable ex) {
|
||||
return new AsyncResult<>(null,
|
||||
(ex instanceof ExecutionException ? (ExecutionException) ex : new ExecutionException(ex)));
|
||||
return new AsyncResult<>(null, ex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the exposed exception: either the cause of a given
|
||||
* {@link ExecutionException}, or the original exception as-is.
|
||||
* @param original the original as given to {@link #forExecutionException}
|
||||
* @return the exposed exception
|
||||
*/
|
||||
private static Throwable exposedException(Throwable original) {
|
||||
if (original instanceof ExecutionException) {
|
||||
Throwable cause = original.getCause();
|
||||
if (cause != null) {
|
||||
return cause;
|
||||
}
|
||||
}
|
||||
return original;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user