我正在尝试实现长轮询,但是在调用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)
我的Servlet如下所示:
@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);
}
}
答案 0 :(得分:1)
根据this JIRA,Weld 1.1.10(存在于Tomcat 7.0.23和相关的JBoss服务器中)存在一个错误,导致Async servlet丢失对同一个servlet的请求之间的上下文。
升级Weld或JBoss版本可以解决问题