AsyncResponse ConnectionCallback не срабатывает в Джерси

Для асинхронного программирования Джерси (JAX-RS) обеспечивает обратный вызов ConnectionCallback, который должен быть выполнен, когда соединение нарушено. Из 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, я могу закрыть, убить или иным образом остановить клиента, который сидит подключен к веб-службе, показанной выше, и ConnectionCallback никогда не запускается.

Я что-то упустил? Включен ли ConnectionCallback в Джерси? (Это необязательно в спецификации JAX-RS, но документы в Джерси говорят об этом, как будто это реализовано.)

Любой ввод будет оценен.

Ответ 1

ConnectionCallback действительно реализован в Джерси. И обратный вызов '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 при написании ответа. Итак, чтобы ответить на ваш вопрос, нет опроса или подобного механизма, который проверяет, подключен ли клиент, а метод onDisconnect вызывается только тогда, когда есть IOException, которое обычно возникает при написании ответа.

Обновление 1:

Также я хотел бы привести ваш собственный вопрос:

"Этот обратный вызов будет выполнен только в том случае, если соединение было преждевременно завершено или утеряно, когда ответ записывается обратно клиент"

Итак, , если вы не попытаетесь записать этот поток, ваш обратный вызов никогда не будет запущен. Чтобы быть понятным, он не должен был вызываться, когда нет ответа на запись или когда ответ равен 202, скорее он должен был вызываться, когда соединение было прервано преждевременно , в то время как ответ записывается.

Я боюсь, что для этой проблемы нет обходной проблемы, если вы не напишите какое-то сетевое программирование низкого уровня с каким-либо опросом. Но я бы не рекомендовал вам пойти на это.

Я предлагаю вам переосмыслить, как вы хотите справиться с этим сбоем.