当前位置: 首页 > 知识库问答 >
问题:

CompletableFuture然后在异常之后撰写

云文栋
2023-03-14

我被CompletableFuture异常处理卡住了。

我的逻辑是发送电子邮件并保存此操作的状态。如果发送电子邮件抛出异常,我需要用异常消息保存状态。

public interface MyService {
CompletableFuture<Boolean> sendEmail(String content, String address);
CompletableFuture<StatusResult> saveStatus(String content, String address);}

处理器类目前有此代码。它工作正常,但对我来说并不优雅。我们如何摆脱用于在阶段之间共享状态的错误本地字段?

@Component
public class Processor {
    private static final Logger LOGGER = LoggerFactory.getLogger(Processor.class);
    @Autowired
    private MyService myService;

    public CompletableFuture<StatusResult> sendEmail(String content, String address) {
        AtomicReference<String> error = new AtomicReference<>();// just to forward error message from exception block to thenCompose
        return myService.sendEmail(content, address).exceptionally(e -> {
            LOGGER.error("Exception during send email ", e);
            error.set(e.getMessage());
            return null;
        }).thenCompose(x -> {
            if (x == null) {
                return myService.saveStatus(error.get(), address);
            } else {
                return myService.saveStatus("good", address);
            }
        });

    }
}

看起来句柄方法应该会有所帮助,但它返回可完成未来的可完成未来

 public CompletableFuture<StatusResult> sendEmail(String content, String address) {
    CompletableFuture<CompletableFuture<StatusResult>> result = myService.sendEmail(content, address).handle((x, e) -> {
        if (e != null) {
            LOGGER.error("Exception during send email ", e);
            return myService.saveStatus("error", address);
        } else {
            return myService.saveStatus("good", address);
        }
    });
}

共有2个答案

阎冠玉
2023-03-14

另一个可行的解决方案:

public CompletableFuture<StatusResult> sendEmailAndSaveStatus(String content, String address) {
    CompletableFuture<Boolean> sendEmail = myService.sendEmail(content, address);
    CompletableFuture<StatusResult> result = new CompletableFuture<>();
    sendEmail.exceptionally(e -> {
        LOGGER.info("Exception during send email ");
        myService.saveStatus(e.getMessage(), address).thenApply(x -> result.complete(x));
        return false;
    });
    sendEmail.thenCompose(x -> myService.saveStatus("good", address)).thenApply(x -> result.complete(x));
    return result;
}
狄德泽
2023-03-14

您可以预先转换为保存状态。

public CompletableFuture<String> sendEmail(String content, String address) {

    return myService.sendEmail(content, address)
            .thenApply(b -> "good")
            .exceptionally(Throwable::getMessage)
            .thenCompose(status -> myService.saveStatus(status, address));
}
 类似资料:
  • 我对函数的契约有一些误解 返回一个新的,当此阶段正常完成时,将此阶段作为提供函数的参数执行。 函数似乎接受这个完成阶段的结果,而不是完成阶段本身。那么这是什么意思呢? 那么由返回的CompletableFuture表示的任务呢? 这是否意味着,由返回的CompletableFuture表示的任务将在与可运行r相同的线程池中执行?

  • 问题内容: 操作系统:Linux,语言:纯C 我将继续学习一般的C编程,在特殊情况下将学习UNIX下的C编程。 使用调用后,我检测到该函数的奇怪行为(对我而言)。 码 输出量 为什么第二个“ Hello”字符串出现在孩子的输出中? 是的,这恰恰是父母在开始时打印的内容,并带有父母的。 但!如果我们在每个字符串的末尾放置一个字符,则会得到预期的输出: 输出 : 为什么会发生?这是正确的行为还是错误?

  • 我一直在玩CompletableFuture,发现了一件奇怪的事情。 如果在我的thenAccept调用中,断言失败,则不会传播异常。当时我尝试了更丑陋的东西: 不会发生任何事情,不会传播任何异常。我尝试使用诸如handle等方法以及与CompletableFutures中异常相关的其他方法,但失败了-没有一个方法像预期的那样传播异常。 当我调试CompletableFuture时,它会捕获如下异

  • 问题内容: 我正在测试具有预期异常的方法。我还需要在引发异常后验证是否在某个模拟对象上调用了一些清除代码,但看起来该验证已被忽略。这是代码。我正在使用Junit 验证预期的异常。 似乎完全被忽略了。无论我采用什么方法,我的测试都通过了,这不是我想要的。 知道为什么会这样吗? 问题答案: 通过将整个测试方法通过JUnit @Rule 包装在try- catch块中来工作。当您的代码引发异常时,它将堆

  • 假设我有这个示例代码,在中遇到了一个异常。我的问题是,这个异常是否会阻止作为在与此代码的调用者方法相同的线程中运行。 我已经浏览了这个主题,它解释了如何处理从异步块抛出的异常(即通过阻塞和使用)。我想知道如果”,块中的代码是否会被执行。 更新: 我运行了一些代码来测试: 它不会打印任何内容,这意味着异常不会从异步块“传播到/到达”调用方方法的线程。我现在了解这里的预期行为,但我有以下问题: 为什么

  • 我正在测试一个具有预期异常的方法。我还需要验证在抛出异常后是否调用了一些清理代码(在模拟对象上),但看起来该验证被忽略了。这是代码。我正在使用 Junit 来验证预期的异常。 似乎完全被忽略了。无论我在中使用什么方法,我的测试都通过了,这不是我想要的。 你知道为什么会发生这种情况吗?