spring-projects / spring-projects/spring-framework
Avoid “No decoder for session id” Exception if session is closed
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 60.2k
- Forks
- 38.8k
- Avg merge
- 5d 2h
- Merged PRs (30d)
- 27
Description
Hello, this is the same issue with https://github.com/spring-projects/spring-framework/issues/24842. Open another one since I can not reopen it because this issue has not been fixed eventually. It still happens occasionally when using org.springframework.web.socket.adapter.standard.StandardWebSocketSession.
The native org.apache.tomcat.websocket.wsSession will set its state finally to CLOSED after calling fireEndpointOnClose when calling StandardWebSocketSession#closeInternal. (tomcat-embed-websocket:10.1.39)
public class WsSession implements Session {
...
public void doClose(CloseReason closeReasonMessage, CloseReason closeReasonLocal, boolean closeSocket) {
if (!state.compareAndSet(State.OPEN, State.OUTPUT_CLOSING)) {
return;
}
...
fireEndpointOnClose(closeReasonLocal);
if (!state.compareAndSet(State.OUTPUT_CLOSING, State.OUTPUT_CLOSED) || closeSocket) {
state.set(State.CLOSED);
closeConnection();
} else {
sessionCloseTimeoutExpiry =
Long.valueOf(System.nanoTime() + TimeUnit.MILLISECONDS.toNanos(getSessionCloseTimeout()));
}
...
}
...
}
The method fireEndpoinOnClose will call the expression this.handler.afterConnectionClosed in org.springframework.web.socket.adapter.standar.StandardWebSocketHandlerAdapter#onClose.
Finally in org.springframework.web.socket.messaging.StompSubProtocolHandler#afterSessionEnded the decoder of the session will be removed.
However, during above process, the state of the session is still OUTPUT_ClOSING which is marked as true for isOpen method as below.
public class WsSession implements Session {
...
@Override
public boolean isOpen() {
return state.get() == State.OPEN || state.get() == State.OUTPUT_CLOSING || state.get() == State.CLOSING;
}
...
}
Therefore, with the fix in previous issue, when the decoder is null for the session, the session might still be in state of OUTPUT_CLOSING.
BTW. This does not happen when using SocketJsSession, because the state will be set to CLOSED, here, before calling afterConnectionClosed
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with StandardWebSocketSession#closeInternal and follow the close callback through StandardWebSocketHandlerAdapter#onClose to StompSubProtocolHandler#afterSessionEnded. Compare the StandardWebSocketSession and AbstractSockJsSession ordering, then verify that a closing standard session does not produce the “No decoder for session id” exception after its decoder is removed.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, spring
- Domain
- backend, networking
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100