gpt4 book ai didi

rest - 带有 Location header 的 JAX-RS AsyncResponse.resume()

转载 作者:行者123 更新时间:2023-12-02 04:55:56 25 4
gpt4 key购买 nike

更新

进一步的挖掘表明,抛出的异常已被丢弃,实际问题是注入(inject)的 UriInfo 无法在 AsyncResponse 的线程中解析!

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

Unable to find contextual data of type: javax.ws.rs.core.UriInfo

原版

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

the origin serverSHOULD send a 201 (Created) response containing a Location headerfield that provides an identifier for the primary resource created(Section 7.1.2) and a representation that describes the status of therequest while referring to the new resource(s).

在编写同步 REST 服务器时,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()
);
});
}

通过反复试验,我发现修改后的位置 header 是造成这种情况的原因。如果我返回实体并设置 201 Created,而不触及 header ,请求最终将得到解析:

@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如果您需要更多信息,请评论!

编辑

一旦我更改任何链接或 header ,请求就会挂起。

最佳答案

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

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

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

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

解决方法:

在任何应返回位置 header 的异步方法中,我仍然在上下文中 .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();
}

关于rest - 带有 Location header 的 JAX-RS AsyncResponse.resume(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31474988/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com