java.lang.IllegalStateException: Not Suspended when AsyncContext#complete()

末鹿安然 提交于 2019-12-25 04:47:51

问题


sometimes my Servlet ends with this exception:

    WARNING: StandardWrapperValve[HeartBeatServlet]: PWC1406: Servlet.service() for servlet HeartBeatServlet threw exception
java.lang.IllegalStateException: Not Suspended
    at com.sun.grizzly.tcp.Response.resume(Response.java:768)
    at org.apache.catalina.connector.Request.asyncComplete(Request.java:3993)
    at org.apache.catalina.connector.AsyncContextImpl.complete(AsyncContextImpl.java:242)
    at com.northcane.talkeen.HeartBeatServlet.doPost(HeartBeatServlet.java:47)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:688)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:770)
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1550)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:281)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:161)
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:331)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:231)
    at com.sun.enterprise.v3.services.impl.ContainerMapper$AdapterCallable.call(ContainerMapper.java:317)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:195)
    at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:860)
    at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:757)
    at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1056)
    at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:229)
    at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
    at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
    at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
    at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)
    at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
    at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
    at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
    at java.lang.Thread.run(Thread.java:722)

and here's my Servlet's source. The only thing it does is to handle long-polling requests from javascript client and sends message received on POST to all of them:

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import javax.servlet.AsyncContext;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


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

    private List<AsyncContext> asyncContextList = new LinkedList<>();

    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response) {
        AsyncContext asyncContext = request.startAsync(request, response);
        asyncContext.setTimeout(30000);
        asyncContextList.add(asyncContext);
    }

    @Override
    public void doPost(HttpServletRequest request, HttpServletResponse response) {
        String test = request.getParameter("message");
        List<AsyncContext> asyncContexts = new ArrayList<>(asyncContextList);
        asyncContextList.clear();
        for (AsyncContext asyncContext : asyncContexts) {
            ServletResponse res = asyncContext.getResponse();
            res.setContentType("text/html");
            try {
                PrintWriter out = asyncContext.getResponse().getWriter();
                out.println(test + " <br />");
                out.flush();
                asyncContext.complete();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

is there something wrong I do? Thanks


回答1:


(The code has Multi-threading issues. Pls see this SO answer for how to resolve them.)

The code is storing the AsyncContext for a GET request in a List and on a POST completes the GET response. But because of the timeout, the GET response may have completed implicitly (triggered by the servlet container) and the stored AsyncContext will not reflect this. So, when you retrieve this stored AsyncContext and try to complete the GET request, the servlet container does not find a pending GET request that needs to be resumed. Hence the IllegalStateException.

Pls also refer this other answer which indirectly answers this.



来源:https://stackoverflow.com/questions/15228031/java-lang-illegalstateexception-not-suspended-when-asynccontextcomplete

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!