更新

更多的挖掘表明,抛出的异常被丢弃,实际的问题是在AsyncResponse的线程中无法解析注入的UriInfo

@Context UriInfo uriInfo;期间访问AsyncResponse.resume()会显示以下LoggableFailure消息:


找不到以下类型的上下文数据:javax.ws.rs.core.UriInfo


原版的

根据RFC 7231 HTTP/1.1 Semantics and ControlPOST应该返回201 CREATED并在标头中提供新资源的位置:


原始服务器
应该发送包含Location标头的201(已创建)响应
为创建的主要资源提供标识符的字段
(第7.1.2节)和描述状态的表述。
请求,同时引用新资源。


编写同步REST Server时,javax.ws.rs.core.Response提供了Response.created()速记,它可以做到这一点。

我将保存新实体,构建一个URI并返回

return Response.created(createURL(created)).build();


但是,当我切换到利用

@Suspended javax.ws.rs.container.AsyncResponse

客户端上的HTTP请求将无限期挂起:

@POST
public void createUser(@Valid User user, @Suspended AsyncResponse asyncResponse) {
    executorService.submit(() -> {
        User created = userService.create(user);
        asyncResponse.resume(
                Response.created(createURL(created)).build()
        );
    });
}


通过反复试验,我发现修改后的位置标头负责。
如果我返回我的实体并设置201 Created而不接触标题,则该请求最终将解决:

@POST
public void createUser(@Valid User user, @Suspended AsyncResponse asyncResponse) {
    executorService.submit(() -> {
        User created = userService.create(user);
        asyncResponse.resume(
                Response.status(Status.CREATED).entity(created).build()  //this works
                //Response.created(createURL(created)).build()
        );
    });
}


所以有什么问题?我误解了这些概念吗?

我在GlassFish4.1上运行RestEasy
如果您需要更多信息,请发表评论!

编辑

一旦我更改了任何链接或标题,该请求就会挂起。

最佳答案

如果有人遇到过同样的问题:

问题是我通过使用@Context UriInfo uriInfo通过注入的.getAbsolutePathBuilder()创建了位置标头。

该方法在同步服务器中有效,因为访问UriInfo的线程仍然具有相同的Request上下文。

但是,当我切换到异步方法时,最终必须访问Runnable的基础uriInfo.getAbsolutePathBuilder()不在任何上下文中-因此会引发异常,从而停止进一步执行。

解决方法:

在任何应返回位置标头的异步方法中,I .getAbsolutePathBuilder()仍在上下文中。然后可以在异步运行中使用UriBuilder实现:

@POST
public void createUser(@Valid User user, @Suspended AsyncResponse asyncResponse) {
    UriBuilder ub = uriInfo.getAbsolutePathBuilder();

    executorService.submit(() -> {
        User created = userService.create(user);
        asyncResponse.resume(
                Response.created(createURL(ub, created)).build()
        );
    });
}

private URI createURL(UriBuilder builder, ApiRepresentation entity) {
    return builder.path(entity.getId().toString()).build();
}

08-27 23:37