AsyncResponse ConnectionCallback不会在Jersey中触发

时间:2014-11-07 04:40:46

标签: java web-services asynchronous jersey jersey-2.0

对于异步编程,Jersey(JAX-RS)提供了一个ConnectionCallback回调,它将在连接断开时执行。来自Jersey docs

  

由于某些异步请求可能需要很长时间才能处理客户端   决定在响应之前终止与服务器的连接   已经恢复或在完全写入客户之前。至   处理这些用例可以使用ConnectionCallback。这个   只有在连接过早的情况下才会执行回调   在将响应写入后面时终止或丢失   客户。请注意,响应时不会调用此回调   写成功,客户端连接按预期关闭。

听起来不错,但我永远无法解决这个问题。

这里有一些代码:

@GET
@Produces(MediaType.TEXT_PLAIN)
@ManagedAsync
@Path("/poll")
public void poll(@Suspended final AsyncResponse asyncResponse) {
    asyncResponse.register(new CompletionCallback() {
        @Override
        public void onComplete(Throwable throwable) {
            logger.info("onComplete called.");
        }
    });

    asyncResponse.register(new ConnectionCallback() {
        @Override
        public void onDisconnect(AsyncResponse disconnected) {
            logger.info("onDisconnect called.");
        }
    });

    asyncResponse.setTimeout(POLL_TIMEOUT_SECONDS, TimeUnit.SECONDS);
    asyncResponse.setTimeoutHandler(new TimeoutHandler() {
        @Override
        public void handleTimeout(AsyncResponse asyncResponse) {
            logger.info("handleTimeout called.");
            asyncResponse.resume(Response.status(Response.Status.OK).entity("TIMEOUT").build());
        }
    });
}

显示的另外两个回调,CompletionCallback和TimeoutHandler,一定会好起来,但不会失败。如果达到指定的超时持续时间,则会触发TimeoutHandler。如果恢复了AsyncResponse实例,则会触发CompletionCallback。

但是,使用ConnectionCallback,我可以关闭,终止或以其他方式停止连接到上面显示的Web服务的客户端,并且ConnectionCallback永远不会被触发。

我错过了什么吗? ConnectionCallback是否在泽西实施? (它在JAX-RS规范中是可选的,但是泽西岛文档谈论它就好像已经实现了。)

任何意见都会受到赞赏。

1 个答案:

答案 0 :(得分:4)

ConnectionCallback确实在Jersey中实现。并且' onDisconnect'也调用了回调。您可以查看泽西岛中的以下代码:

https://github.com/jersey/jersey/blob/a6ff4d50da13d45ad90fd7375a15a31afa02e489/core-server/src/main/java/org/glassfish/jersey/server/ServerRuntime.java#L723

https://github.com/jersey/jersey/blob/b7907e279010e7035a7a3e529993d22f77a21e08/core-server/src/main/java/org/glassfish/jersey/server/ChunkedOutput.java#L246-L252

在编写响应时,如果出现IOException,则抛出这些内容。因此,为了回答您的问题,没有轮询或类似机制继续检查客户端是否已连接,而只有在编写响应时通常会发生IOException时才会调用 onDisconnect 方法。 / p>

更新1:

我还想引用你自己的问题:

  

"只有在连接过早的情况下才会执行此回调   在将响应写入后面时终止或丢失   客户机"

所以,除非您尝试写入该流,否则您的回调将永远不会被触发。要清楚,当没有写入响应或响应是202时,它不应该被调用,而是当连接过早地终止时它意味着被调用,而响应是写作

我担心除非你编写一些带有某种轮询的低级网络编程,否则没有解决这个问题的方法。但我不建议你这样做。

我建议您重新考虑处理此故障的方式。