diff --git a/dependencies/pom.xml b/dependencies/pom.xml
index 3a2c2e3aff1..c94b3494246 100644
--- a/dependencies/pom.xml
+++ b/dependencies/pom.xml
@@ -92,7 +92,7 @@
2.2.0
3.3.1
1.4
- 2.1.1
+ 3.0
1.0.3
2.2
1.1.1
diff --git a/fault-tolerance/src/main/java/io/helidon/faulttolerance/RetryImpl.java b/fault-tolerance/src/main/java/io/helidon/faulttolerance/RetryImpl.java
index 69707be46c1..3eabf49cc0d 100644
--- a/fault-tolerance/src/main/java/io/helidon/faulttolerance/RetryImpl.java
+++ b/fault-tolerance/src/main/java/io/helidon/faulttolerance/RetryImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Oracle and/or its affiliates.
+ * Copyright (c) 2020, 2021 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,7 +23,6 @@
import java.util.concurrent.Flow;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Supplier;
@@ -78,9 +77,10 @@ private Single retrySingle(RetryContext extends CompletionStage> con
long nanos = System.nanoTime() - context.startedNanos;
if (nanos > maxTimeNanos) {
- return Single.error(new TimeoutException("Execution took too long. Already executing: "
- + TimeUnit.NANOSECONDS.toMillis(nanos) + " ms, must timeout after: "
- + TimeUnit.NANOSECONDS.toMillis(maxTimeNanos) + " ms."));
+ return Single.error(new RetryTimeoutException(context.throwable(),
+ "Execution took too long. Already executing: "
+ + TimeUnit.NANOSECONDS.toMillis(nanos) + " ms, must timeout after: "
+ + TimeUnit.NANOSECONDS.toMillis(maxTimeNanos) + " ms."));
}
if (currentCallIndex > 0) {
@@ -120,9 +120,10 @@ private Multi retryMulti(RetryContext extends Flow.Publisher> contex
long nanos = System.nanoTime() - context.startedNanos;
if (nanos > maxTimeNanos) {
- return Multi.error(new TimeoutException("Execution took too long. Already executing: "
- + TimeUnit.NANOSECONDS.toMillis(nanos) + " ms, must timeout after: "
- + TimeUnit.NANOSECONDS.toMillis(maxTimeNanos) + " ms."));
+ return Multi.error(new RetryTimeoutException(context.throwable(),
+ "Execution took too long. Already executing: "
+ + TimeUnit.NANOSECONDS.toMillis(nanos) + " ms, must timeout after: "
+ + TimeUnit.NANOSECONDS.toMillis(maxTimeNanos) + " ms."));
}
if (currentCallIndex > 0) {
diff --git a/fault-tolerance/src/main/java/io/helidon/faulttolerance/RetryTimeoutException.java b/fault-tolerance/src/main/java/io/helidon/faulttolerance/RetryTimeoutException.java
new file mode 100644
index 00000000000..fc62c476e35
--- /dev/null
+++ b/fault-tolerance/src/main/java/io/helidon/faulttolerance/RetryTimeoutException.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.helidon.faulttolerance;
+
+import java.util.concurrent.TimeoutException;
+
+/**
+ * Subclass of {@link TimeoutException} to discern exceptions thrown by a {@link Retry}
+ * when its overall timeout is reached versus those thrown by a {@link Timeout}.
+ */
+public class RetryTimeoutException extends TimeoutException {
+ private static final long serialVersionUID = 1900926677490550714L;
+
+ private final Throwable lastRetryException;
+
+ /**
+ * Constructs a {@code RetryTimeoutException} with the specified detail
+ * message.
+ *
+ * @param throwable last retry exception
+ * @param message the detail message
+ */
+ public RetryTimeoutException(Throwable throwable, String message) {
+ super(message);
+ lastRetryException = throwable;
+ }
+
+ /**
+ * Last exception thrown in {@code Retry} before the overall timeout reached.
+ *
+ * @return last exception thrown
+ */
+ public Throwable lastRetryException() {
+ return lastRetryException;
+ }
+}
+
diff --git a/microprofile/fault-tolerance/etc/spotbugs/exclude.xml b/microprofile/fault-tolerance/etc/spotbugs/exclude.xml
new file mode 100644
index 00000000000..3bd3f33cb33
--- /dev/null
+++ b/microprofile/fault-tolerance/etc/spotbugs/exclude.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/microprofile/fault-tolerance/pom.xml b/microprofile/fault-tolerance/pom.xml
index 6f9d5e1b58a..4bf4b9c3acf 100644
--- a/microprofile/fault-tolerance/pom.xml
+++ b/microprofile/fault-tolerance/pom.xml
@@ -1,7 +1,7 @@
+ org.awaitility
+ awaitility
+ 4.0.3
+