java - CompleteableFuture 抛出异常时返回 500 内部错误

标签 java dropwizard

我有一个带有端点的休息 Controller :

@GET
@Path("/reindex-record")
public String reindexRecord(@QueryParam("id") String id) {
    if (StringUtils.isEmpty(id)) {
        CompletableFuture.runAsync(
            () -> runWithException(Reindexer::reindexAll));
    } else {
        CompletableFuture.runAsync(() -> runWithException(
            () -> Reindexer.reindexOne(id)));
    }

    // return "ok" or throw WebApplciationException from runWithException method below
}

这是我的包装方法 - 两种方法 - reindexAll 和 reindexOne 都会抛出已检查的异常,因此决定使用包装方法和接口(interface):

public interface RunnableWithException {
    void run() throws Exception; 
}

private void runWithException(RunnableWithException task) {
    try {
        task.run();
    } catch (Exception e) {
        log.error("Error occured during async task execution", e);
        throw new WebApplicationException(
            Response.status(Response.Status.INTERNAL_SERVER_ERROR)
                .entity("Internal error occurred").build());
    }
}

问题是我想使用 CompleteableFuture 异步运行此任务,并且仅在给定任务完成后或者出现错误抛出带有 INTERNAL_SERVER_ERROR 状态的 WebApplicationException 时才给出响应。

您将如何在我的用例中使用 if/else 实现这一点?

编辑: 截至目前我有这个方法:

@GET
@Path("/reindex-record")
public String reindexRecord(@QueryParam("id") String id) throws ExecutionException,
    InterruptedException {
    CompletableFuture<Void> task;
    if (StringUtils.isEmpty(id)) {
        task = CompletableFuture.runAsync(
            () -> runWithException(Reindexer::reindexAll));
    } else {
        task = CompletableFuture.runAsync(() -> runWithException(
            () -> Reindexer.reindexOne(id)));
    }
    return task.thenApply(x -> "ok")
        .exceptionally(throwable -> {
            log.error("Error occured during async task execution", throwable);
            throw new WebApplicationException(Response.status(Response.Status.SERVICE_UNAVAILABLE)
                                                  .entity("Internal error occurred. Try again later")
                                                  .build());

        }).get();

}

但是,如果任何 Reindexer 方法抛出错误,我仍然会收到带有数据的状态 500:

{
"code": 500,
"message": "There was an error processing your request. It has been logged (ID 03f09a62b62b1649)."

}

而不是我的异常(exception) block 中定义的503。 如果重要的话,将 dropwizard 与 JAX-RS 一起使用。

最佳答案

您可以将方法的主体更改为:

@GET
@Path("/reindex-record")
public String reindexRecord(@QueryParam("id") String id) {
    final CompletableFuture<Void> future;
    if (StringUtils.isEmpty(id)) {
        future = CompletableFuture.runAsync(
            () -> runWithException(Reindexer::reindexAll));
    } else {
        future = CompletableFuture.runAsync(
            () -> runWithException(() -> Reindexer.reindexOne(id)));
    }

    // this will block
    future.get();

    return "ok";
}

通过存储 future,您可以调用它的 get() 方法,该方法将阻塞,直到 future 完成。

来自CompletableFuture.get()的javadoc:

Waits if necessary for this future to complete, and then returns its result.

关于java - CompleteableFuture 抛出异常时返回 500 内部错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51399766/

相关文章:

java - 如何从谷歌应用程序调用.Net网络服务?

java - 我如何在一个简单的类文件中获取 ServletContext 对象?

java - 在没有大量查询的情况下,在 where 子句中使用 ArrayList 中的值?

java - 如何使用 Visual Studio Code 调试 java dropwizard 应用程序

java - 根据三个旋转器中的输入从一项 Activity 转移到另一项 Activity

java - 将目录添加到 java.library.path 后 System.loadLibrary() 出现 UnsatisfiedLinkError

java - 如何使用 Mockito 模拟 feign.Client.Default

logback - 在 SLF4J 中使用 JSON 日志记录时如何包含多个 JSON 字段?

java - Hibernate + Dropwizard,MySQLSyntaxErrorException : Unknown database 'test_db;'

java - Swagger Dropwizard 0.7 - 不显示 JSON 参数的 TextArea