I have a custom WebSocket handler (for a custom sub-protocol), registered the usual way:
public class WSConfig implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) {
webSocketHandlerRegistry
.addHandler(new PerConnectionWebSocketHandler(CustomProtocolHandler.class), endpointUrl);
}
}
Inside CustomProtocolHandler all methods inherited from WebSocketHandler (e.g. afterConnectionEstablished, handleMessage etc) receive WebSocketSession which is not thread-safe. The official tutorial says ConcurrentWebSocketSessionDecorator can be used to prevent concurrent writes, but by the time my custom handler is hit it is already too late to wrap the session.
public class CustomProtocolHandler implements WebSocketHandler, SubProtocolCapable {
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) {
//This is not safe
session.sendMessage(...);
//And this this doesn't make sense
new ConcurrentWebSocketSessionDecorator(session).sendMessage(...);
}
}
Now, I see that Spring's own SubProtocolWebSocketHandler (which, like mine, implements WebSocketHandler and SubProtocolCapable) does decorate the session internally, and I was hoping I'd be able to use it as the basis, but to create SubProtocolWebSocketHandler I need MessageChannel which comes from spring-messaging. I neither use Spring Messaging, nor have any clue how I would get a MessageChannel. Should I be implementing a custom one?
So, how is ConcurrentWebSocketSessionDecorator intended to be used? I would expect a way to register session-wrapping logic with the webSocketHandlerRegistry, but nope. The only idea I have is to maintain yet another ConcurrentHashMap that maps the raw session (or its ID) to a wrapper, but that's horrible and the one thing I don't need is more state to manage and clean up.