Spring Websockets
Biju Kunjummen
Disclaimer!!
Content heavily copied from the followed sources:
- http://www.slideshare.net/sergialmar/websockets-with-spring-4
- https://github.com/rstoyanchev/spring-websocket-portfolio
- Intro to Websocket applications with Spring Framework 4.0 - https://spring.io/blog/2014/01/21/springone2gx-2013-replay-intro-to-websocket-applications-with-spring-framework-4-0
- Building Websocket browser apps with Spring: http://spring.io/blog/2013/10/23/webinar-replay-building-websocket-browser-applications-with-spring
WebSocket
demo: hello-world, tail-file
"mechanism for browser-based applications...
two-way communication with servers...
does not rely on multiple HTTP connections"
- RFC 6455, The WebSocket Protocol
WebSocket
- A thin layer on top of raw TCP
- Full Duplex, stateful connnection., stays open for an entire session
- Stream of messages, not just raw bytes
- Uses port 80, uses http for initial handshake
Reality!
- Not supported in IE < 10 - http://caniuse.com/websockets
- Issues with proxies
- Not a replacement for Ajax/polling/long polling/comet
- Socket is very low level to work on
- Requires Messaging/Event driven architecture
When to use it
Low latency, high frequency of messages between client and server
- Collaboration/Chat, Google docs
- Games
- Financial trading applications
Otherwise, chose polling/long polling/comet
- Latest Story, latest tweet
HANDSHAKE REQUEST
GET /mychat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat
Sec-WebSocket-Version: 13
Origin: http://example.com
HANDSHAKE RESPONSE
HTTP / 1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat
Typical API Lifecycle Events
demo:spring-websocket-test
- open - session established
- message - new messages received
- error - transport error
- close - session closed
Symmetrical on the client and server sides
Java API for WebSocket - JSR-356
- Tomcat 7.0.47+
- Jetty 9.1+
- Glassfish 4 with Tyrus WebSocket engine
- Wildfly 8.0+
Sockjs
- Emulate WebSocket API as close as possible
- At least one streaming protocol per major browser
- Polling in old browsers, hosts behind restrictive proxies
Sockjs URL Scheme
demo: spring-websocket-test
- GET /echo
- GET /echo/info
- POST /echo/**server**/**session**/**transport**
WebSocket API - Very Low Level
Single WebSocket connection per client
results in single @ServerEndpoint per application
limits you to one annotated class
Not the right level of abstraction--
much like plain Servlet is too course-grained
Raw WebSocket
demo: spring-websocket-portfolio
A message is a blank page--
you can write anything (custom format?)
Can't provide useful annotations--
How to broadcast to some subset of users?
Spring's WebSocket API
- Abstraction over WebSocket runtimes, Including JSR-356 containers, but not limited to it-
- Supports transparent fallback options based on SockJS protocol
- STOMP sub-protocol support
- Abstractions for building messaging architectures--
Message, MessageChannel, MessageHandler
STOMP Protocol
- Simple protocol for asynchronous message passing
- Originally for scripting languages (Ruby, Python)
- Supported by message brokers
- Suited for use on the web
- Frames modelled on HTTP
Stomp frame content
COMMAND
header1:value1
header2:value2
body^@
Client-to-Server Commands
SEND
SUBSCRIBE
UNSUBSCRIBE
Server-to-Client Commands
MESSAGE
ERROR
RECEIPT
ACK
NACK
Sample client to server communication
SEND
destination: /queue/trade
content-type: application/json
content-length: 46
{"action":"Buy","ticker":"CIS", "shares":"44"}^@
Client Consumes a message(1)
SUBSCRIBE
id:sub-1
destination: /topic/price.stock.*
^@
Client Consumes a message(1)
MESSAGE
message-id:kdaldj
subscription:sub-1
destination:/topic/price.stock.CIS
{"ticker":"CIS","price":"24"}^@
STOMP vs Raw Websockets
- Standard message format
- Browser client support (e.g. stomp.js, msgs.js)
- Common messaging patterns
- Ability to incorporate (full-featured) message broker
Spring - Configuring for Websocket with STOMP/SOCKJS fallback support
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketDefaultConfig extends AbstractWebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableStompBrokerRelay("/topic/");
config.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/helloworld").withSockJS();
}
}
Spring - Sample servicing a request from the client
@MessageMapping("/greetings")
@SendTo("/topic/greetings")
public String handleGreeting(@Payload String greeting) {
String message = "[" + getTimestamp() + "]:" + greeting;
oldMessages.add(message);
return message;
}
SEND
destination:/app/greetings
content-type:application/json
content-length:11
Hello world^@a
Spring - Subscribing to messages
demo: hello-world, sample-chat
@SubscribeMapping("/oldmessages")
public List<String> oldMessages() {
return Arrays.asList(oldMessages.toArray(new String[0]));
}
SUBSCRIBE
destination:/app/oldmessages
^@
References
- http://www.slideshare.net/sergialmar/websockets-with-spring-4
- https://github.com/rstoyanchev/spring-websocket-portfolio
- Intro to Websocket applications with Spring Framework 4.0 - https://spring.io/blog/2014/01/21/springone2gx-2013-replay-intro-to-websocket-applications-with-spring-framework-4-0
- Building Websocket browser apps with Spring: http://spring.io/blog/2013/10/23/webinar-replay-building-websocket-browser-applications-with-spring