JEE6 Длинный веб-сервер опроса — исключение после вызова AsyncContext #завершено

#jakarta-ee #glassfish #servlet-3.0

#джакарта-ee #glassfish #сервлет-3.0

Вопрос:

Я пытаюсь реализовать длительный опрос, однако после вызова AsyncContext.complete() я получаю исключение из Weld:

 Warnung:   Error invoking requestDestroyed method on ServletRequestListener org.jboss.weld.servlet.WeldListener
java.lang.NullPointerException
    at org.jboss.weld.context.AbstractBoundContext.deactivate(AbstractBoundContext.java:71)
    at org.jboss.weld.context.http.HttpRequestContextImpl.deactivate(HttpRequestContextImpl.java:70)
    at org.jboss.weld.servlet.WeldListener.requestDestroyed(WeldListener.java:154)
    at org.apache.catalina.core.StandardContext.fireRequestDestroyedEvent(StandardContext.java:5261)
    at org.apache.catalina.core.StandardHostValve.postInvoke(StandardHostValve.java:255)
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:359)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:260)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:188)
    at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:191)
    at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:168)
    at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:189)
    at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:288)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:206)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:136)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:114)
    at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
    at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:838)
    at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:113)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:115)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:55)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:135)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:564)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:544)
    at java.lang.Thread.run(Thread.java:744)
  

Мой сервлет выглядит следующим образом:

 @WebServlet(urlPatterns = {"/newmsg"}, asyncSupported = true)
public class NewMessageNotifierLongPolling extends HttpServlet {

    private static final Queue<AsyncContext> peers = new ConcurrentLinkedQueue();

    public void notifyClientsAboutNewMessage(@Observes Message msg) {
        for (final AsyncContext ac : peers) {
            try {
                final ServletOutputStream os = ac.getResponse().getOutputStream();
                os.println(msg.getSubject());
                ac.complete();
            } catch (IOException ex) {
                Logger.getLogger(NewMessageNotifierLongPolling.class.getName()).log(Level.SEVERE, null, ex);
            } finally {
                peers.remove(ac);
            }
        }
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType(MediaType.TEXT_PLAIN);
        response.setStatus(202);
        response.setHeader("Pragma", "no-cache");
        response.setCharacterEncoding("UTF-8");
        response.flushBuffer();

        final AsyncContext ac = request.startAsync(request, response);
        ac.setTimeout(35 * 1000);
        ac.addListener(new AsyncListener() {
            @Override
            public void onComplete(AsyncEvent event) throws IOException {
                peers.remove(ac);
            }

            @Override
            public void onTimeout(AsyncEvent event) throws IOException {
                peers.remove(ac);
            }

            @Override
            public void onError(AsyncEvent event) throws IOException {
                peers.remove(ac);
            }

            @Override
            public void onStartAsync(AsyncEvent event) throws IOException {
            }
        });
        peers.add(ac);
    }
}
  

Комментарии:

1. Это может вас заинтересовать: issues.jboss.org/browse/WELD-1020

2. Спасибо, что указали на это.

3. Насколько я понимаю, вы ответили на вопрос, я с радостью приму его, если вы опубликуете его в качестве ответа.

4. Итак, вы обновили Weld или Jboss?

5. На данный момент я ничего не изменил, это ошибка в AS. Поскольку в настоящее время я разрабатываю только примеры приложений на основе JEE6 (отсюда и длинный опрос вместо WebSockets). Я просто переключился на JBoss КАК 7 на время.

Ответ №1:

Согласно этому JIRA, в Weld 1.1.10 есть ошибка (присутствующая в Tomcat 7.0.23 и связанных серверах JBoss), из-за которой асинхронный сервлет теряет контекст между запросами к одному и тому же сервлету.

Обновление версий Weld или JBoss устраняет проблему