JAX-RS и длинный опрос

Я пытаюсь использовать длинный опрос с JAX-RS (реализация Джерси), и это не работает, как я ожидаю. Может быть, я что-то неправильно понимаю. Буду признателен за любые советы.

Обратите внимание, что использование обратного подключения (что-то вроде Atmosphere, Comet и т. д.) не является вариантом из соображений безопасности. Не то чтобы я сейчас разрабатываю Tomcat 7.

Следующий метод вызывается из вызова JQuery Ajax (с использованием $.ajax).

@Path("/poll")
@GET
public void poll(@Suspended final AsyncResponse asyncResponse)
        throws InterruptedException {
    new Thread(new Runnable() {
        @Override
        public void run() {
            this.asyncResponse = asyncResponse;
            // wait max. 30 seconds using a CountDownLatch
            latch.await(getTimeout(), TimeUnit.SECONDS);
        }
    }).start();
}

Другой метод вызывается из моего приложения (после вызова JMS):

@POST
@Path("/printed")
public Response printCallback() {
    // ...

    // I expect the /poll call to be ended here from the client perspective but that is not the case
    asyncResponse.resume("UPDATE"); 
    latch.countDown();

    return Response.ok().build();
}

Если я удалю создание потока в методе poll. Тогда это работает, но проблема в том, что поток занят. Если я использую создание потока, то метод возвращается напрямую, и браузер не обнаруживает конец длинного опроса.

Что я делаю неправильно?


person LaurentG    schedule 23.10.2013    source источник


Ответы (1)


Я нашел решение своей проблемы. Проблема была в конфигурации. Мы должны указать, что сервлет из Джерси поддерживает async и тогда он работает нормально:

<servlet>
    <servlet-name>Jersey REST Service</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    <async-supported>true</async-supported>
    ...
</servlet>

Обратите внимание, что если у вас есть фильтры сервлетов, они также должны быть от async-supported до true..

Это также не было необходимо, чтобы создать поток. Джерси делает это за меня:

@Path("/poll")
@GET
public void poll(@Suspended final AsyncResponse asyncResponse)
        throws InterruptedException {
    asyncResponse.setTimeout(30, TimeUnit.SECONDS);
    this.asyncResponse = asyncResponse;
}

@POST
@Path("/printed")
public Response printCallback(String barcode) throws IOException {
    // ...

    this.asyncResponse.resume("MESSAGE");

    return Response.ok().build();
}

При вызове poll браузер ожидает получения MESSAGE или получения статуса HTTP 503, если время ожидания истекло. На сервере поток запросов не блокируется до истечения времени ожидания, а освобождается напрямую. На стороне клиента у меня есть JavaScript, который снова вызывает метод, если происходит тайм-аут, в противном случае я что-то обрабатываю на странице.

person LaurentG    schedule 28.10.2013
comment
Как вы обнаружили, что вам не нужно явно создавать поток? В примерах в документации Джерси они создают поток: jersey.java.net/documentation /latest/async.html - person raspacorp; 01.05.2014
comment
Я это видел. Я предполагаю, что это проблема в примерах. Потоки не должны создаваться самим кодом, иначе в чем преимущество асинхронных запросов? Кроме того, это работает без ручного создания потока. Если для параметра «асинхронная поддержка» установлено значение true, сервер приложений создает поток. Я проверил это с помощью отладчика. - person LaurentG; 01.05.2014
comment
Но разве вы не пропустили аннотацию @ManagedAsync в своем методе опроса? см. jersey.java.net/apidocs/2.7 /джерси/org/glassfish/джерси/сервер/ - person raspacorp; 01.05.2014
comment
Или, может быть, «@ManagedAsync» — это просто более конкретный способ (на уровне метода) сообщить Джерси, что он должен создать поток для асинхронного метода, вместо ‹async-supported›true‹/async-supported›, который работает на уровень сервлета - person raspacorp; 02.05.2014
comment
Ты прав. @ManagedAsync относится к Джерси. Я обычно предпочитаю стандартный способ. - person LaurentG; 02.05.2014