Сервлет 3.0: Не удается отправить асинхронный ответ? - PullRequest
1 голос
/ 11 мая 2011

У меня проблемы с установкой AsyncContexts для пользователей и использованием их для отправки им уведомлений.При загрузке страницы у меня есть некоторый код jQuery для отправки запроса:

$.post("TestServlet",{
    action: "registerAsynchronousContext"
        },function(data, textStatus, jqXHR){
            alert("Server received async request"); //Placed here for debugging   
  }, "json");

И в "TestServlet" у меня есть этот код в методе doPost:

HttpSession userSession = request.getSession();
String userIDString = userSession.getAttribute("id").toString();

String paramAction = request.getParameter("action");

if(paramAction.equals("registerAsynchronousContext"))
{              
    AsyncContext userAsyncContext = request.startAsync();

    HashMap<String, AsyncContext> userAsynchronousContextHashMap = (HashMap<String, AsyncContext>)getServletContext().getAttribute("userAsynchronousContextHashMap");
    userAsynchronousContextHashMap.put(userIDString, userAsyncContext);
    getServletContext().setAttribute("userAsynchronousContextHashMap", userAsynchronousContextHashMap);

    System.out.println("Put asynchronous request in global map");
}

    //userAsynchronousContextHashMap is created by a ContextListener on the start of the web-app

Однако, согласно OperaПохоже, что Dragonfly (инструмент отладки, такой как Firebug) отправляет ответ HTTP 500 через 30000 мс после отправки запроса.

Любые ответы, созданные с помощью userAsyncContext.getResponse (). GetWriter (). Print (SOME_JSON).) и отправлено до того, как ответ HTTP 500 не получен браузером, и я не знаю почему.Использование обычного объекта ответа для отправки ответа (response.print (SOME_JSON)) принимается браузером ТОЛЬКО если отсутствует весь код в операторе «if», касающемся AsyncContext.

Может кто-нибудь мне помочьиз?У меня есть ощущение, что это связано с моим неправильным пониманием того, как работает асинхронный API.Я думал, что смогу сохранить эти AsyncContexts в глобальной карте, затем извлечь их и использовать их объекты ответа, чтобы передавать вещи клиентам.Однако не похоже, что AsyncContexts может выполнить обратную запись для клиентов.

Любая помощь будет оценена.

Ответы [ 2 ]

5 голосов
/ 11 мая 2011

Я решил проблему. Кажется, что с моим подходом было несколько проблем:

  1. В Glassfish все объекты AsyncContext имеют период ожидания по умолчанию 30 000 миллисекунд (.5 минут). По истечении этого периода весь ответ передается обратно клиенту, что означает, что вы не сможете использовать его снова.

    Если вы реализуете длинный опрос, это может не быть большой проблемой (поскольку в любом случае вы в конечном итоге отправите еще один запрос после ответа), но если вы хотите реализовать потоковую передачу (отправка данных обратно клиенту без отправки ответа) вы захотите либо увеличить время ожидания, либо избавиться от всего этого вместе. Это можно сделать с помощью метода .setTimeout() в AsyncContext. Обратите внимание, что в то время как spec гласит: «Значение тайм-аута ноль или меньше означает отсутствие тайм-аута.», Glassfish (в это время), по-видимому, интерпретирует 0 как «требуется немедленный ответ» и любое отрицательное число как "нет времени ожидания".

  2. Если вы реализуете потоковую передачу, вы должны использовать метод .flush() печатающего устройства, чтобы передать данные клиенту после того, как вы закончите, используя методы .print() .println() или .write() для записи данные.

  3. На стороне клиента, если вы передали данные, он вызовет состояние готовности 3 («интерактивный», что означает, что браузер находится в процессе получения ответа). Если вы используете jQuery, простого способа обработки readyStates из 3 не существует, поэтому вам придется вернуться к обычному Javascript, чтобы и отправлять запрос, и обрабатывать ответ, если вы реализуете потоковую передачу.

2 голосов
/ 26 июня 2012

Я заметил, что в Glassfish, если вы используете AsyncContext и используете .setTimeOut () для отрицательного числа, соединение в любом случае разрывается, чтобы это исправить, я должен был перейти к своему веб-конфигуратору администратора Glassfish: asadmin set configs.config.server-config.network-config.protocols.protocol.http-слушатель-1.http. И установите время ожидания -1. Все это, чтобы стеклянные рыбы не заканчивали соединения через 30 сек.

...