Skip to content

Commit a708779

Browse files
committed
Altered Failsafe's exception policy to only throw FailsafeExceptions if an execution fails due to a checked Exception. Closes failsafe-lib#66.
1 parent aaa5cd2 commit a708779

File tree

4 files changed

+32
-20
lines changed

4 files changed

+32
-20
lines changed

CHANGES.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
# 1.0.0
2+
3+
### API Changes
4+
5+
* Failsafe will now only throw `FailsafeException` when an execution fails with a checked `Exception`. See [issue #66](https://github.com/jhalterman/failsafe/issues/66) for details.
6+
17
# 0.9.5
28

39
### Bug Fixes

src/main/java/net/jodah/failsafe/SyncFailsafe.java

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ public class SyncFailsafe<R> extends FailsafeConfig<R, SyncFailsafe<R>> {
4848
* exceeded.
4949
*
5050
* @throws NullPointerException if the {@code callable} is null
51-
* @throws FailsafeException if the {@code callable} fails with a Throwable and the retry policy is exceeded, or if
52-
* interrupted while waiting to perform a retry.
51+
* @throws FailsafeException if the {@code callable} fails with a checked Exception or if interrupted while waiting to
52+
* perform a retry.
5353
* @throws CircuitBreakerOpenException if a configured circuit is open.
5454
*/
5555
public <T> T get(Callable<T> callable) {
@@ -61,8 +61,8 @@ public <T> T get(Callable<T> callable) {
6161
* exceeded.
6262
*
6363
* @throws NullPointerException if the {@code callable} is null
64-
* @throws FailsafeException if the {@code callable} fails with a Throwable and the retry policy is exceeded, or if
65-
* interrupted while waiting to perform a retry.
64+
* @throws FailsafeException if the {@code callable} fails with a checked Exception or if interrupted while waiting to
65+
* perform a retry.
6666
* @throws CircuitBreakerOpenException if a configured circuit is open.
6767
*/
6868
public <T> T get(ContextualCallable<T> callable) {
@@ -73,8 +73,8 @@ public <T> T get(ContextualCallable<T> callable) {
7373
* Executes the {@code runnable} until successful or until the configured {@link RetryPolicy} is exceeded.
7474
*
7575
* @throws NullPointerException if the {@code runnable} is null
76-
* @throws FailsafeException if the {@code callable} fails with a Throwable and the retry policy is exceeded, or if
77-
* interrupted while waiting to perform a retry.
76+
* @throws FailsafeException if the {@code callable} fails with a checked Exception or if interrupted while waiting to
77+
* perform a retry.
7878
* @throws CircuitBreakerOpenException if a configured circuit is open.
7979
*/
8080
public void run(CheckedRunnable runnable) {
@@ -85,8 +85,8 @@ public void run(CheckedRunnable runnable) {
8585
* Executes the {@code runnable} until successful or until the configured {@link RetryPolicy} is exceeded.
8686
*
8787
* @throws NullPointerException if the {@code runnable} is null
88-
* @throws FailsafeException if the {@code callable} fails with a Throwable and the retry policy is exceeded, or if
89-
* interrupted while waiting to perform a retry.
88+
* @throws FailsafeException if the {@code runnable} fails with a checked Exception or if interrupted while waiting to
89+
* perform a retry.
9090
* @throws CircuitBreakerOpenException if a configured circuit is open.
9191
*/
9292
public void run(ContextualRunnable runnable) {
@@ -116,8 +116,8 @@ public AsyncFailsafe<R> with(Scheduler scheduler) {
116116
/**
117117
* Calls the {@code callable} synchronously, performing retries according to the {@code retryPolicy}.
118118
*
119-
* @throws FailsafeException if the {@code callable} fails with a Throwable and the retry policy is exceeded or if
120-
* interrupted while waiting to perform a retry
119+
* @throws FailsafeException if the {@code callable} fails with a checked Exception or if interrupted while waiting to
120+
* perform a retry.
121121
* @throws CircuitBreakerOpenException if a configured circuit breaker is open
122122
*/
123123
@SuppressWarnings("unchecked")
@@ -156,7 +156,7 @@ private <T> T call(Callable<T> callable) {
156156
return result;
157157
if (fallback != null)
158158
return fallbackFor((R) result, failure);
159-
throw failure instanceof FailsafeException ? (FailsafeException) failure : new FailsafeException(failure);
159+
throw failure instanceof RuntimeException ? (RuntimeException) failure : new FailsafeException(failure);
160160
} else {
161161
try {
162162
Thread.sleep(execution.getWaitTime().toMillis());
@@ -175,7 +175,7 @@ private <T> T fallbackFor(R result, Throwable failure) {
175175
try {
176176
return (T) fallback.apply(result, failure);
177177
} catch (Exception e) {
178-
throw e instanceof FailsafeException ? (FailsafeException) e : new FailsafeException(e);
178+
throw e instanceof RuntimeException ? (RuntimeException) e : new FailsafeException(e);
179179
}
180180
}
181181
}

src/test/java/net/jodah/failsafe/FailsafeConfigTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ public void testListenersForUnhandledFailure() throws Throwable {
205205
RetryPolicy retryPolicy = new RetryPolicy().retryOn(IllegalStateException.class).withMaxRetries(10);
206206

207207
// When
208-
Asserts.assertThrows(() -> registerListeners(Failsafe.with(retryPolicy)).get(callable), FailsafeException.class,
208+
Asserts.assertThrows(() -> registerListeners(Failsafe.with(retryPolicy)).get(callable),
209209
IllegalArgumentException.class);
210210

211211
// Then
@@ -230,7 +230,7 @@ public void testListenersForRetriesExceeded() throws Throwable {
230230
RetryPolicy retryPolicy = new RetryPolicy().abortOn(IllegalArgumentException.class).withMaxRetries(3);
231231

232232
// When
233-
Asserts.assertThrows(() -> registerListeners(Failsafe.with(retryPolicy)).get(callable), FailsafeException.class,
233+
Asserts.assertThrows(() -> registerListeners(Failsafe.with(retryPolicy)).get(callable),
234234
IllegalStateException.class);
235235

236236
// Then
@@ -256,7 +256,7 @@ public void testListenersForAbort() throws Throwable {
256256
RetryPolicy retryPolicy = new RetryPolicy().abortOn(IllegalArgumentException.class).withMaxRetries(3);
257257

258258
// When
259-
Asserts.assertThrows(() -> registerListeners(Failsafe.with(retryPolicy)).get(callable), FailsafeException.class,
259+
Asserts.assertThrows(() -> registerListeners(Failsafe.with(retryPolicy)).get(callable),
260260
IllegalArgumentException.class);
261261

262262
// Then

src/test/java/net/jodah/failsafe/SyncFailsafeTest.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import java.util.concurrent.ExecutionException;
3232
import java.util.concurrent.ScheduledExecutorService;
3333
import java.util.concurrent.TimeUnit;
34+
import java.util.concurrent.TimeoutException;
3435
import java.util.concurrent.atomic.AtomicInteger;
3536

3637
import org.testng.annotations.BeforeMethod;
@@ -44,10 +45,10 @@
4445
public class SyncFailsafeTest extends AbstractFailsafeTest {
4546
// Results from a synchronous Failsafe call
4647
private @SuppressWarnings("unchecked") Class<? extends Throwable>[] syncThrowables = new Class[] {
47-
FailsafeException.class, ConnectException.class };
48+
ConnectException.class };
4849
// Results from a get against a future that wraps a synchronous Failsafe call
4950
private @SuppressWarnings("unchecked") Class<? extends Throwable>[] futureSyncThrowables = new Class[] {
50-
ExecutionException.class, FailsafeException.class, ConnectException.class };
51+
ExecutionException.class, ConnectException.class };
5152

5253
@BeforeMethod
5354
protected void beforeMethod() {
@@ -78,7 +79,7 @@ private void assertRun(Object runnable) throws Throwable {
7879
// When / Then
7980
assertThrows(() -> {
8081
run(Failsafe.with(retryTwice), runnable);
81-
} , syncThrowables);
82+
}, syncThrowables);
8283
verify(service, times(3)).connect();
8384
}
8485

@@ -158,8 +159,7 @@ public void shouldThrowOnNonRetriableFailure() throws Throwable {
158159
RetryPolicy retryPolicy = new RetryPolicy().retryOn(ConnectException.class);
159160

160161
// When / Then
161-
assertThrows(() -> Failsafe.with(retryPolicy).get(() -> service.connect()), FailsafeException.class,
162-
IllegalStateException.class);
162+
assertThrows(() -> Failsafe.with(retryPolicy).get(() -> service.connect()), IllegalStateException.class);
163163
verify(service, times(3)).connect();
164164
}
165165

@@ -251,6 +251,12 @@ public void shouldCompleteWhenMaxDurationExceeded() throws Throwable {
251251
verify(service).connect();
252252
}
253253

254+
public void shouldWrapCheckedExceptions() throws Throwable {
255+
assertThrows(() -> Failsafe.with(new RetryPolicy().withMaxRetries(1)).run(() -> {
256+
throw new TimeoutException();
257+
}), FailsafeException.class, TimeoutException.class);
258+
}
259+
254260
private void run(SyncFailsafe<?> failsafe, Object runnable) {
255261
if (runnable instanceof CheckedRunnable)
256262
failsafe.run((CheckedRunnable) runnable);

0 commit comments

Comments
 (0)