将可完成的未来的异常映射到不同的异常类型?
Map exception in completable future to a different exception type?
我正在使用 java 8 的可完成期货,我希望能够接受未来抛出的异常并将其转换为不同的异常。
我尝试过的所有复合材料似乎一旦发生异常就会短路。
例如,使用 scala future,我可以做这样的事情:
scala.concurrent.Future<Object> translatedException = ask.recover(new Recover<Object>() {
@Override public Object recover(final Throwable failure) throws Throwable {
if (failure instanceof AskTimeoutException) {
throw new ApiException(failure);
}
throw failure;
}
}, actorSystem.dispatcher());
我希望能够在 java 的未来复合块中模仿它。这可能吗?
您可以使用 CompletableFuture#handle(BiFunction)
。例如
CompletableFuture<String> ask = CompletableFuture.supplyAsync(() -> {
throw new IndexOutOfBoundsException();
});
CompletableFuture<String> translatedException = ask.handle((r, e) -> {
if (e != null) {
if (e instanceof IndexOutOfBoundsException) {
throw new IllegalArgumentException();
}
// fallback
if (e instanceof RuntimeException) {
throw (RuntimeException) e;
}
throw new RuntimeException(e);
}
return r;
});
如果 ask
完成但出现异常,则 translatedException
将完成并出现可能已转换的异常。否则,它将具有相同的成功结果值。
关于我在代码中的评论,handle
方法需要 BiFunction
,其 apply
方法未声明为抛出 Throwable
。因此,lambda 主体本身不能抛出 Throwable
。参数 e
的类型是 Throwable
所以你不能直接 throw
它。如果你知道它是那种类型,你可以将它转换为 RuntimeException
,或者你可以将它包装在 RuntimeException
和 throw
中。
请注意,e 始终是 java.util.concurrent.CompletionException
。
CompletableFuture<String> ask = CompletableFuture.supplyAsync(() -> {
throw new IndexOutOfBoundsException();
});
CompletableFuture<String> translatedException = ask.handle((r, e) -> {
if (e != null) {
if (e.getCause() instanceof IndexOutOfBoundsException) {
throw new IllegalArgumentException();
}
throw (RuntimeException) e; // this is sketchy, handle it differently, maybe by wrapping it in a RuntimeException
}
return r;
});
我正在使用 java 8 的可完成期货,我希望能够接受未来抛出的异常并将其转换为不同的异常。
我尝试过的所有复合材料似乎一旦发生异常就会短路。
例如,使用 scala future,我可以做这样的事情:
scala.concurrent.Future<Object> translatedException = ask.recover(new Recover<Object>() {
@Override public Object recover(final Throwable failure) throws Throwable {
if (failure instanceof AskTimeoutException) {
throw new ApiException(failure);
}
throw failure;
}
}, actorSystem.dispatcher());
我希望能够在 java 的未来复合块中模仿它。这可能吗?
您可以使用 CompletableFuture#handle(BiFunction)
。例如
CompletableFuture<String> ask = CompletableFuture.supplyAsync(() -> {
throw new IndexOutOfBoundsException();
});
CompletableFuture<String> translatedException = ask.handle((r, e) -> {
if (e != null) {
if (e instanceof IndexOutOfBoundsException) {
throw new IllegalArgumentException();
}
// fallback
if (e instanceof RuntimeException) {
throw (RuntimeException) e;
}
throw new RuntimeException(e);
}
return r;
});
如果 ask
完成但出现异常,则 translatedException
将完成并出现可能已转换的异常。否则,它将具有相同的成功结果值。
关于我在代码中的评论,handle
方法需要 BiFunction
,其 apply
方法未声明为抛出 Throwable
。因此,lambda 主体本身不能抛出 Throwable
。参数 e
的类型是 Throwable
所以你不能直接 throw
它。如果你知道它是那种类型,你可以将它转换为 RuntimeException
,或者你可以将它包装在 RuntimeException
和 throw
中。
请注意,e 始终是 java.util.concurrent.CompletionException
。
CompletableFuture<String> ask = CompletableFuture.supplyAsync(() -> {
throw new IndexOutOfBoundsException();
});
CompletableFuture<String> translatedException = ask.handle((r, e) -> {
if (e != null) {
if (e.getCause() instanceof IndexOutOfBoundsException) {
throw new IllegalArgumentException();
}
throw (RuntimeException) e; // this is sketchy, handle it differently, maybe by wrapping it in a RuntimeException
}
return r;
});