Sunday, March 18, 2018

Spring WebSocket STOMP tips and tricks

Recently we successfully implemented secure Websockets in one of our projects and learned a lot of tricks to get things working together. Given below are some tips that would help teams embarking on implementing WebSockets in their programs.

1)  Spring uses the STOMP protocol for Web Sockets. The other popular protocol for Web Sockets is WAMP, but Spring does not support it. Hence if you are using Spring, make sure that your Android, iOS and JS  libraries support STOMP.

2)  Spring websocket library by default also supports SockJS as a fall-back for web JS clients. If your use-case only entails supporting Android and iOS clients, then disable SockJS in your Spring configuration. It might happen that a use-case might work on SockJS on a web-client, but fail in native mobile code.

3) The default SockJS implementation of Spring, sends a server heartbeat header (char 'h') every 25 seconds to the clients. Hence there is no timeout on the socket connection for JS clients. But on mobile apps (pure STOMP), there is no heartbeat configured by default. Hence we have to explicitly set the heartbeat on the server OR on the client to keep the connection alive when idle. Otherwise, idle connections get dropped after 1 minute. Reference Links: https://stackoverflow.com/questions/28841505/spring-4-stomp-websockets-heartbeat
Sample server side code below.

4) One Android websocket library that works very well with Spring websockets is https://github.com/NaikSoftware/StompProtocolAndroid. But unfortunately, this library does not support heartbeats. Hence you have to explicitly send heartbeats using sample code like this - https://github.com/NaikSoftware/StompProtocolAndroid/issues/18.

5) On iOS, the following socket library worked very well with Spring websockets - https://github.com/rguldener/WebsocketStompKit. We faced an issue, where this library was throwing Array Index Range exceptions on server side heartbeat messages, but we made small changes in this library to skip process for heart-beat header messages.

6)  It is recommended to give the URL scheme as wss://, although we found that https:// was also working fine. If you have SockJS enabled on Spring, then please append the URL with /websocket, as you would get a exception stating invalid protocol up-gradation. Hence clients should subscribe to/{endpoint}/websocket. https://github.com/rstoyanchev/spring-websocket-portfolio/issues/14

7)  Both libraries also support sending headers during the CONNECT step. Very often, teams send the authorization token during the CONNECT step in the header, that can be used to authenticate the client. To access these headers on the server we need to access the Nativeheaders hashmap. Sample code - https://github.com/rsparkyc/WebSocketServer/blob/master/src/main/java/hello/ConnectionListener.java