connection explanation upgrade HTTP to Websocket 1 2 3 ws:// localhost:port/{stomp endpoint}/ {serverid}/{sessionid}/ websocket
stomp endpoint To define the path prefix to upgrade websocket. This can be done in following spring configuration.
1 2 3 4 5 @Override public void registerStompEndpoints (final StompEndpointRegistry registry) { registry.addEndpoint("/chat" ); registry.addEndpoint("/chat" ).withSockJS(); }
serverid A required but useless id in spring-websocket
sessionid Probably the most important id
in this protocol, used to communicate back to current user.
subscribe 1 2 3 "SUBSCRIBE\n id:{subscriptionid}\n destination:{path}\n \n \u0000 "
subscriptionid A unique id to indicate single subscription. Mostly useless.
path Extremely important for usage of listening backward communication.
In spring-websocket, it is by default prefix as /user
. In order to allow this prefix to pass the path validation, we should configure the simple broker path in spring configuration as following.
1 2 3 4 @Override public void configureMessageBroker (final MessageBrokerRegistry config) { config.enableSimpleBroker("/user" ); }
So by using the following code, the entire path will be /user/to-userid/queue
.
1 this .template.convertAndSendToUser("to-userid" , "/queue" , "message content" );
This is why it is so important, that by listening to this path, this single user would get message that is specific to it
send 1 "SEND\n from:{from-userid}\n destination:/{prefix}/{destination}/{to-userid}\n content-length:29\n \n {\" message\" :\" message content\" }\u0000 "
from-userid to indicate send message from whom. We may have better to do it in future, but for now, just put it here.
prefix 1 2 3 4 @Override public void configureMessageBroker (final MessageBrokerRegistry config) { config.setApplicationDestinationPrefixes("/websocket" ); }
destination This destination can be configured using the following annotation, this annotation is important to indicate the method below is a handler to deal with message that matches the path format in ant
syntax.
The following example defines the destination as user
1 @MessageMapping("/user/{to-userid}")
to-userid Extremely important to indicate whom to receive this message.
By using the same annotation.
1 2 3 @MessageMapping("/user/{to-userid}")
command Some useful log to indicate different command.
disconnect 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 2021-06-04 15:45:49.465 DEBUG 15378 --- [boundChannel-26] org.springframework.web.SimpLogging : Processing DISCONNECT session =58oec3gc 2021-06-04 15:45:49.465 DEBUG 15378 --- [nio-8080-exec-5] s.w.s.h.LoggingWebSocketHandlerDecorator : WebSocketServerSockJsSession[id =58oec3gc] closed with CloseStatus[code =1000, reason =null ] 2021-06-04 15:45:49.465 DEBUG 15378 --- [nio-8080-exec-5] o.s.w.s.m.SubProtocolWebSocketHandler : Clearing session 58oec3gc 2021-06-04 15:45:49.465 DEBUG 15378 --- [tboundChannel-8] o.s.w.s.m.SubProtocolWebSocketHandler : No session for GenericMessage [payload =byte[0], headers={simpMessageType =DISCONNECT_ACK, simpDisconnectMessage =GenericMessage [payload =byte[0], headers={simpMessageType =DISCONNECT, stompCommand =DISCONNECT, simpSessionAttributes={}, simpHeartbeat=[J@1e9284c7, simpSessionId =58oec3gc}], simpSessionId =58oec3gc}] 2021-06-04 15:45:49.466 DEBUG 15378 --- [boundChannel-29] org.springframework.web.SimpLogging : Processing DISCONNECT session =58oec3gc 2021-06-04 15:45:49.467 DEBUG 15378 --- [tboundChannel-9] o.s.w.s.m.SubProtocolWebSocketHandler : No session for GenericMessage [payload =byte[0], headers={simpMessageType =DISCONNECT_ACK, simpDisconnectMessage =GenericMessage [payload =byte[0], headers={simpMessageType =DISCONNECT, stompCommand =DISCONNECT, simpSessionAttributes={org.springframework.messaging.simp.SimpAttributes.COMPLETED =true }, simpSessionId =58oec3gc}], simpSessionId =58oec3gc}] 2021-06-04 15:45:56.194 DEBUG 15378 --- [MessageBroker-8] o.s.w.s.s.t.h.DefaultSockJsService : Closed 1 sessions: [58oec3gc]
subscribe 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 2021 -06 -04 15 :46 :48.714 DEBUG 15378 --- [nio-8080-exec-6] o.s .web .servlet .DispatcherServlet : GET "/chat/info" , parameters={}2021 -06 -04 15 :46 :48.714 DEBUG 15378 --- [nio-8080-exec-6] o.s .w .s .s .s .WebSocketHandlerMapping : Mapped to org.springframework .web .socket .sockjs .support .SockJsHttpRequestHandler@625 d91322021 -06 -04 15 :46 :48.714 DEBUG 15378 --- [nio-8080-exec-6] o.s .w .s .s .t .h .DefaultSockJsService : Processing transport request: GET http:2021 -06 -04 15 :46 :48.714 DEBUG 15378 --- [nio-8080-exec-6] o.s .web .servlet .DispatcherServlet : Completed 200 OK2021 -06 -04 15 :46 :48.791 DEBUG 15378 --- [nio-8080-exec-7] o.s .web .servlet .DispatcherServlet : GET "/chat/080/bw6hxi0f/websocket" , parameters={}2021 -06 -04 15 :46 :48.791 DEBUG 15378 --- [nio-8080-exec-7] o.s .w .s .s .s .WebSocketHandlerMapping : Mapped to org.springframework .web .socket .sockjs .support .SockJsHttpRequestHandler@625 d91322021 -06 -04 15 :46 :48.791 DEBUG 15378 --- [nio-8080-exec-7] o.s .w .s .s .t .h .DefaultSockJsService : Processing transport request: GET http:2021 -06 -04 15 :46 :48.793 DEBUG 15378 --- [nio-8080-exec-7] o.s .web .servlet .DispatcherServlet : Completed 101 SWITCHING_PROTOCOLS2021 -06 -04 15 :46 :48.794 DEBUG 15378 --- [nio-8080-exec-7] s.w .s .h .LoggingWebSocketHandlerDecorator : New WebSocketServerSockJsSession[id=bw6hxi0f] 2021 -06 -04 15 :46 :48.797 DEBUG 15378 --- [boundChannel-32] org.springframework .web .SimpLogging : Processing CONNECT session=bw6hxi0f2021 -06 -04 15 :46 :48.800 DEBUG 15378 --- [boundChannel-35] org.springframework .web .SimpLogging : Processing SUBSCRIBE /topic/messages id=sub-0 session=bw6hxi0f
send 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 2021-06-04 15:47:57.442 DEBUG 15378 --- [boundChannel-37] .WebSocketAnnotationMethodMessageHandler : Searching methods to handle SEND /app/chat session =bw6hxi0f, lookupDestination ='/chat' 2021-06-04 15:47:57.444 DEBUG 15378 --- [boundChannel-37] .WebSocketAnnotationMethodMessageHandler : Invoking ChatController#send[2 args] simpMessageType : MESSAGE stompCommand : SEND nativeHeaders : {destination=[/app/chat], content-length=[26]} simpSessionAttributes : {} simpHeartbeat : [J@5b8852c9 lookupDestination : /chat simpSessionId : bw6hxi0f simpDestination : /app/chatFrom : [a] Content: [aaaa] 2021-06-04 16:14:07.627 DEBUG 16527 --- [boundChannel-13] org.springframework.web.SimpLogging : Processing MESSAGE destination =/queue/messages-usertest session =test payload={"from" :"a" ,"text" :"aaaaa" ,"time" :"16:14" }
message 1 2 3 4 5 2021-06-04 15:47:57.491 DEBUG 15378 --- [boundChannel-37] org.springframework.web.SimpLogging : Processing MESSAGE destination =/topic/messages session =bw6hxi0f payload={"from" :"a" ,"text" :"aaaa" ,"time" :"15:47" } 2021-06-04 15:47:57.492 DEBUG 15378 --- [boundChannel-37] org.springframework.web.SimpLogging : Broadcasting to 1 sessions.