Tyrus websocket: IllegalStateException cannot set WriteListener for non-async request

Deadly 提交于 2019-11-28 02:17:52

java.lang.IllegalStateException: Cannot set WriteListener for non-async or non-upgrade request

In order for a request to be fully asynchronous, any Filter in the request-response chain must explicitly be set to support asynchronous requests. Specifically those "catch-all" filters which are mapped on /*.

In case the filter is registered via <filter> entry in web.xml, this can be done by setting child element <async-supported> to true.

<filter>
    ...
    <async-supported>true</async-supported>
</filter>

In case the filter is registered via @WebFilter annotation, this can be done by setting its asyncSupported attribute to true.

@WebFilter(..., asyncSupported="true")

In case the filter is registered via ServletContext#addFilter(), this can be done by setting Registration.Dynamic#setAsyncSupported(). to true.

Dynamic filter = servletContext.addFilter(name, type);
filter.setAsyncSupported(true);

Reason is, the WebSocket implementation internally uses ServletRequest#startAsync() during the handshake request in order to keep the request-response pipeline "forever" open until the response is explicitly closed. Its javadoc says the following:

Throws
IllegalStateException - if this request is within the scope of a filter or servlet that does not support asynchronous operations (that is, isAsyncSupported() returns false), or if this method is called again without any asynchronous dispatch (resulting from one of the AsyncContext.dispatch() methods), is called outside the scope of any such dispatch, or is called again within the scope of the same dispatch, or if the response has already been closed

The isAsyncSupported() defaults to false in order to not break existing web applications using poorly implemented servlet filters. Technically, it should suffice to mark only the target Servlet as async supported and leave the filters alone. A sane "catch-all" Filter wouldn't explicitly write anything to the HTTP response, but the Servlet API did never forbid that and thus such filters can unfortunately exist.

In case you have one such filter, then you should either fix it to not write anything to the response anymore so that you can safely mark it to support async requests, or to adjust its URL pattern to not cover WebSocket requests. I.e. don't map it on /* anymore.

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