Letting CompletableFuture exceptionally() handle a supplyAsync() Exception

瘦欲@ 提交于 2021-01-01 04:17:58

问题


The question is rather simple: I'm looking for an elegant way of using CompletableFuture#exceptionally alongside with CompletableFuture#supplyAsync. This is what does not work:

private void doesNotCompile() {
    CompletableFuture<String> sad = CompletableFuture
            .supplyAsync(() -> throwSomething())
            .exceptionally(Throwable::getMessage);
}

private String throwSomething() throws Exception {
    throw new Exception();
}

I thought the idea behind exceptionally() was precisely to handle cases where an Exception is thrown. Yet if I do this it works:

private void compiles() {
    CompletableFuture<String> thisIsFine = CompletableFuture.supplyAsync(() -> {
        try {
            throwSomething();
            return "";
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }).exceptionally(Throwable::getMessage);
}

I could work with that, but it looks horrible and makes things harder to maintain. Is there not a way to keep this clean which doesn't require transforming all the Exception into RuntimeException ?


回答1:


This might not be a super popular library, but we use it (and from times to times I do some work there too; minor though) internally: NoException. It is really, really nicely written for my taste. This is not the only thing it has, but definitely covers your use case:

Here is a sample:

import com.machinezoo.noexception.Exceptions;
import java.util.concurrent.CompletableFuture;

public class SO64937499 {

    public static void main(String[] args) {
        CompletableFuture<String> sad = CompletableFuture
            .supplyAsync(Exceptions.sneak().supplier(SO64937499::throwSomething))
            .exceptionally(Throwable::getMessage);
    }

    private static String throwSomething() throws Exception {
        throw new Exception();
    }
}

Or you can create these on your own:

final class CheckedSupplier<T> implements Supplier<T> {

    private final SupplierThatThrows<T> supplier;

    CheckedSupplier(SupplierThatThrows<T> supplier) {
        this.supplier = supplier;
    }

    @Override
    public T get() {
        try {
            return supplier.get();
        } catch (Throwable exception) {
            throw new RuntimeException(exception);
        }
    }
}



@FunctionalInterface
interface SupplierThatThrows<T> {

    T get() throws Throwable;
}

And usage:

 CompletableFuture<String> sad = CompletableFuture
        .supplyAsync(new CheckedSupplier<>(SO64937499::throwSomething))
        .exceptionally(Throwable::getMessage);


来源:https://stackoverflow.com/questions/64937499/letting-completablefuture-exceptionally-handle-a-supplyasync-exception

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!