JAX-RS AsyncResponse.resume() 位置 header
JAX-RS AsyncResponse.resume() with Location header
更新
更多的挖掘表明抛出的异常被丢弃,实际问题是注入的 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 Control,POST
应该 return 201 CREATED
并在 header:
中提供新资源的位置
the origin server
SHOULD send a 201 (Created) response containing a Location header
field that provides an identifier for the primary resource created
(Section 7.1.2) and a representation that describes the status of the
request while referring to the new resource(s).
编写同步 REST 服务器时,javax.ws.rs.core.Response
提供 Response.created()
shorthand 正是这样做的。
我会保存新实体,构建一个 URI
和 return
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()
);
});
}
通过trial-and-error发现修改位置header负责。
如果我 return 我的实体并设置 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
如果您需要更多信息,请发表评论!
编辑
只要我更改任何 link 或 header,请求就会挂起。
如果有人遇到同样的问题:
问题是我通过使用 .getAbsolutePathBuilder()
.
的注入 @Context UriInfo uriInfo
创建了位置 header
该方法适用于同步服务器,因为访问 UriInfo 的线程仍然具有相同的请求上下文。
但是,当我切换到异步方法时,最终必须访问 uriInfo.getAbsolutePathBuilder()
的底层 Runnable
不在任何上下文中 - 因此抛出一个停止进一步执行的异常。
解决方法:
在任何应该 return 位置 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();
}
更新
更多的挖掘表明抛出的异常被丢弃,实际问题是注入的 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 Control,POST
应该 return 201 CREATED
并在 header:
the origin server SHOULD send a 201 (Created) response containing a Location header field that provides an identifier for the primary resource created (Section 7.1.2) and a representation that describes the status of the request while referring to the new resource(s).
编写同步 REST 服务器时,javax.ws.rs.core.Response
提供 Response.created()
shorthand 正是这样做的。
我会保存新实体,构建一个 URI
和 return
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()
);
});
}
通过trial-and-error发现修改位置header负责。
如果我 return 我的实体并设置 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 如果您需要更多信息,请发表评论!
编辑
只要我更改任何 link 或 header,请求就会挂起。
如果有人遇到同样的问题:
问题是我通过使用 .getAbsolutePathBuilder()
.
@Context UriInfo uriInfo
创建了位置 header
该方法适用于同步服务器,因为访问 UriInfo 的线程仍然具有相同的请求上下文。
但是,当我切换到异步方法时,最终必须访问 uriInfo.getAbsolutePathBuilder()
的底层 Runnable
不在任何上下文中 - 因此抛出一个停止进一步执行的异常。
解决方法:
在任何应该 return 位置 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();
}