У меня есть следующая трассировка стека в журнале каталины:
24-Jan-2019 16:44:13.139 INFO [messageBrokerScheduler-3] org.apache.coyote.AbstractProcessor.setErrorState An error occurred in processing while on a non-container thread. The connection will be closed immediately
java.io.IOException: An existing connection was forcibly closed by the remote host
at sun.nio.ch.SocketDispatcher.write0(Native Method)
.....
at org.apache.catalina.connector.ResponseFacade.flushBuffer(ResponseFacade.java:312)
at org.springframework.http.server.ServletServerHttpResponse.flush(ServletServerHttpResponse.java:96)
at org.springframework.web.socket.sockjs.transport.session.AbstractHttpSockJsSession.writeFrameInternal(AbstractHttpSockJsSession.java:350)
at org.springframework.web.socket.sockjs.transport.session.AbstractSockJsSession.writeFrame(AbstractSockJsSession.java:322)
at org.springframework.web.socket.sockjs.transport.session.AbstractSockJsSession.sendHeartbeat(AbstractSockJsSession.java:255)
at org.springframework.web.socket.sockjs.transport.session.AbstractSockJsSession$HeartbeatTask.run(AbstractSockJsSession.java:456)
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Как видно из трассировки стека, в AbstractSockJsSession есть исключение $ HeartbeatTask.run (AbstractSockJsSession.java:456)
Из исходного кода spring-websocket мы имеем следующее:
private class HeartbeatTask implements Runnable {
private boolean expired;
@Override
public void run() {
synchronized (responseLock) {
if (!this.expired && !isClosed()) {
try {
sendHeartbeat();
}
catch (Throwable ex) {
// Ignore: already handled in writeFrame...
}
finally {
this.expired = true;
}
}
}
}
void cancel() {
this.expired = true;
}
}
Как видно, метод sendHeartbeat () оборачивается блоком try-catch.
Итак, не можете понять, как это возможно, что tomcat печатает это исключение?
Я использую spring-websocket 4.3.8, tomcat 8.5.9
JFYI:
Я знаю, что блок catch был добавлен в версии Spring-websocket 4.3.8, поэтому я использую 4.3.8
Также я знаю, что в Tomcat 8.5.25 setErrorState регистрирует сообщение в режиме отладки.