SlideShare a Scribd company logo
WebSockets with Spring 4
Sergi Almar
@sergialmar
Who I am
•

CTO @ Voz.io

•

Spring Certified Trainer

•

javaHispano Core Member

•

Spring I/O conference organiser
Collaborative Apps
Multiplayer Games
Multimedia Chat
Social Feeds
Sports Updates
Financial Tickets
Clickstream Data
Online Education
Location-based Apps
Real-Time Data on the Web
•

Polling

•

Long Polling / Comet

•

Flash
Problem

Applications need two-way communication
Too many connections and overhead with ajax / comet
WebSockets

two-way communication done right
WebSocket Protocol / RFC 6455
•

Real-time full duplex communication over TCP

•

Uses port 80 / 443 (URL scheme: ws:// and wss://)

•

Small overhead for text messages (frames)
•

•

0x00 for frame start, 0xFF for frame end (vs HTTP 1Kb)

Ping / pong frames for staying alive
WebSocket Handshake
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!

client sends a WebSocket handshake request
HTTP/1.1 101 Switching Protocols!
Upgrade: websocket!
Connection: Upgrade!
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=!
Sec-WebSocket-Protocol: chat!

server response
JS WebSocket API
var ws = new WebSocket("ws://www.java2days.com/ws");!

!
// When the connection is open, send some data to the server!
ws.onopen = function () {!
ws.send('Here I am!');!
};!

!
// Log messages from the server!
ws.onmessage = function (event) {!
console.log('message: ' + event.data);!
};!

!
ws.onclose = function (event) {!
console.log('closed:' + event.code);!
};!
Java WebSocket Implementations
•

Multiple implementations before the standard

•

JSR-356 (May 2013)
•

Reference implementation Tyrus (bundled with
Glassfish 4)

•

Rewrite across containers (tomcat 8.0.0-RC5, Jetty
9.1…)
WebSockets.springify()
Spring WebSockets
•

WebSockets are now supported in Spring 4

•

Fallback options with SockJS

•

STOMP over WebSocket

•

Foundation for messaging architecture
WebSocket Handlers
public class EchoHandler extends TextWebSocketHandlerAdapter {!

!
@Override!
public void handleTextMessage(WebSocketSession session, !
! ! ! ! ! ! ! ! ! ! TextMessage message) throws Exception {!
session.sendMessage(message);!
}!
!
}
WebSocket Config
@Configuration!
@EnableWebSocket!
public class WsConfig implements WebSocketConfigurer {!

!
!

!

@Override!
public void registerWebSocketHandlers(!
! ! ! ! ! ! ! ! ! WebSocketHandlerRegistry registry) {!

!
registry.addHandler(new EchoHandler(), "/echo");!
}!
}!
Per-Session Handler
Previous example showed how to configure a global handler

•

•

but you may want to have a stateful per-session handler

@Configuration!
@EnableWebSocket!
public class WsConfig implements WebSocketConfigurer {!

!

!

@Bean!
DI
public WebSocketHandler echoHandler() {!
return new PerConnectionWebSocketHandler(EchoHandler.class);!
}!
@Override!
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {!
registry.addHandler(echoHandler(), "/echo");!
}!

}
Can anyone join the party?

http://caniuse.com/#feat=websockets / DEC 2013
SockJS

dude, where are my socks?
SockJS
•

Coherent, cross-browser, Javascript API for full duplex
communication.

•

Close to HTML5 WebSockets API

•

Client and server side implementation (ruby, node…
and also in spring-websockets)
SocksJS API
var sock = new SockJS('http://www.java2days.com/ws');!

!
sock.onopen = function() {!
sock.send('Here I am');
};!

!

!
sock.onmessage = function(event) {!
console.log('message', e.data);!
};!

!
sock.onclose = function() {!
console.log('close');!
};!
SockJS URLs
•

Base URL: /base_url

•

Info test: /base_url/info

•

Session URL: /base_url/server/session
Enabling SocksJS
@Configuration!
@EnableWebSocket!
public class WsConfig implements WebSocketConfigurer {!

!
!

!

@Override!
public void registerWebSocketHandlers(!
! ! ! ! ! ! ! ! ! WebSocketHandlerRegistry registry) {!

!
registry.addHandler(new EchoHandler(), “/echo”).withSockJS();!
}!
}!

MessageHandler doesn’t change
(SocketJsService delivers the message to the handler regardless of the protocol)
Problem
•

WebSockets are too low level and different from
HTTP / REST

•

We need asynchronous, event-driven, reactive
programming style

•

Mmmm, that sounds familiar: JMS, AMQP… 

but we still want to stick to the Spring MVC
programming model
Here’s were we are…
…but we want something like this
Solution
•

Stomp over WebSocket

•

Some Spring Integration types have been promoted to
the core
•
•

•

Message, MessageChannel, MessageHandler…
@MessageMapping, @SubscribeEvent…

New spring-messaging module
STOMP
STOMP
•

Simple interoperable protocol for asynchronous messaging

•

Supported by Apache ActiveMQ, RabbitMQ, HornetQ…

•

Frames modelled on HTTP

var socket = new SockJS('/myapp/echo');!
var client = Stomp.over(socket);

COMMAND!
header1:value1!
header2:value2!
!
Body^@!
Client Frames
•

SEND a message

•

SUBSCRIBE / UNSUBSCRIBE from destination

•

ACK / NACK the reception of a message (optional by
default)
Server Frames
•

Convey a MESSAGE from subscription to the client

•

Send RECEIPT when server has successfully
processed a client frame

•

Send an ERROR if something goes wrong
Configuration
!
@Configuration!
@EnableWebSocketMessageBroker!
public class Config implements WebSocketMessageBrokerConfigurer {!

!
@Override!
public void registerStompEndpoints(StompEndpointRegistry r){!
r.addEndpoint("/stomp");!
}!

!
@Override!
public void configureMessageBroker(MessageBrokerConfigurer c){!
c.enableSimpleBroker("/topic/");!
Subscriptions
c.setApplicationDestinationPrefixes("/app");!
processed by spring
}!

!
}!

simple broker
Sending Messages
stomp.js
stompClient.send("/app/trade", {}, JSON.stringify(trade));

prefix
SEND!
destination:/app/trade!
content-type:application/json!
content-length:47!

!
{"action":"Sell","ticker":"DELL","shares":"10"}!

supports ant-style patterns
@MessageMapping("/trade")!
public void executeTrade(Trade trade, Principal principal) {!
! trade.setUsername(principal.getName());!
! this.tradeService.executeTrade(trade);!
}
Handler Methods
•

Flexible handler method signatures
•

@PathVariable, @Header/@Headers, @Payload, Message, Principal

•

Message converters
@Controller!
public class ChatController {!

!
@MessageMapping("/message")!
public void sendMessage(String message, Principal principal) {!
// ...!
}!
}!
Handler Methods
•

Can also return a value
!
!
!

Return wrapped in a Message and sent to /topic/message
@MessageMapping("/message")!
public String sendMessage(String message) {!
return message.toUpperCase();!
}

!
•

Or define the destination with @SendTo
@MessageMapping("/message")!
@SendTo("/topic/spring-room")!
public String sendMessage(String message) {!
return message.toUpperCase();!
}!
Intercepting Subscriptions
stompClient.subscribe("/app/positions", function(message) {!
...!
});!
SUBSCRIBE!
id:sub-0!
destination:/app/positions!
@Controller!
public class PortfolioController {!

!
@SubscribeEvent("/positions")!
public List<Position> getPositions(Principal p) {!
Portfolio portfolio = ...!
return portfolio.getPositions();!
}!
}

sent directly to the client, not going
though the message broker
User destinations
•

User specific queues can be used
•
•

•

/user/** kind of paths
queues with unique id will be created

Useful to send user related information or errors

client.subscribe("/user/queue/private-messages", function(msg) {!
// ...!
});!

!
client.subscribe("/user/queue/errors", function(msg) {!
// ...!
});!
Sending to user
@Controller!
public class ChatController {!
Will be sent to /user/{username}/queue/message
!
@MessageMapping("/message")!
@SendToUser!
public String sendMessage(String message) {!
return message.toUpperCase();!
}!
!
@MessageExceptionHandler!
@SendToUser("/queue/errors")!
public String handleException(IllegalStateException ex) {!
return ex.getMessage();!
}!
!
}!
SimpMessagingTemplate
•

Sending messages without handler methods

template.convertAndSend("/topic/chat", message;!
template.convertAndSendToUser(user, dest, message;
Using a Message Broker
•

Previous configuration used Spring’s simple broker
•
•

•

Not suitable for clustering
Subset of STOMP

A message broker can be plugged-in instead
Message Broker Config
@Configuration!
@EnableWebSocketMessageBroker!
public class Config implements WebSocketMessageBrokerConfigurer{!
!
@Override!
public void configureMessageBroker(MessageBrokerConfigurer c){!
c.enableStompBrokerRelay("/queue/", "/topic/");!
c.setApplicationDestinationPrefixes("/app");!
}!
}
Thanks!
@sergialmar

More Related Content

What's hot (20)

PDF
Lessons learned from writing over 300,000 lines of infrastructure code
Yevgeniy Brikman
 
PPTX
Terraform training 🎒 - Basic
StephaneBoghossian1
 
PDF
Terraform 0.12 + Terragrunt
Anton Babenko
 
PPTX
Node js Introduction
sanskriti agarwal
 
PDF
Deploying Flink on Kubernetes - David Anderson
Ververica
 
PDF
Apache Bigtop3.2 (仮)(Open Source Conference 2022 Online/Hiroshima 発表資料)
NTT DATA Technology & Innovation
 
PDF
Amazon S3 Best Practice and Tuning for Hadoop/Spark in the Cloud
Noritaka Sekiyama
 
PDF
(Big) Data Serialization with Avro and Protobuf
Guido Schmutz
 
PDF
アーキテクチャから理解するPostgreSQLのレプリケーション
Masahiko Sawada
 
PPTX
Elastic stack Presentation
Amr Alaa Yassen
 
PDF
Deep Dive into Spark SQL with Advanced Performance Tuning with Xiao Li & Wenc...
Databricks
 
PDF
Mvcc in postgreSQL 권건우
PgDay.Seoul
 
PPT
Logstash
琛琳 饶
 
PDF
Terraform: Infrastructure as Code
Pradeep Bhadani
 
PDF
Spark SQL Deep Dive @ Melbourne Spark Meetup
Databricks
 
PDF
PostgreSQL Deep Internal
EXEM
 
PDF
Materialized Column: An Efficient Way to Optimize Queries on Nested Columns
Databricks
 
PDF
Why does my choice of storage matter with cassandra?
Johnny Miller
 
PDF
Understanding PostgreSQL LW Locks
Jignesh Shah
 
Lessons learned from writing over 300,000 lines of infrastructure code
Yevgeniy Brikman
 
Terraform training 🎒 - Basic
StephaneBoghossian1
 
Terraform 0.12 + Terragrunt
Anton Babenko
 
Node js Introduction
sanskriti agarwal
 
Deploying Flink on Kubernetes - David Anderson
Ververica
 
Apache Bigtop3.2 (仮)(Open Source Conference 2022 Online/Hiroshima 発表資料)
NTT DATA Technology & Innovation
 
Amazon S3 Best Practice and Tuning for Hadoop/Spark in the Cloud
Noritaka Sekiyama
 
(Big) Data Serialization with Avro and Protobuf
Guido Schmutz
 
アーキテクチャから理解するPostgreSQLのレプリケーション
Masahiko Sawada
 
Elastic stack Presentation
Amr Alaa Yassen
 
Deep Dive into Spark SQL with Advanced Performance Tuning with Xiao Li & Wenc...
Databricks
 
Mvcc in postgreSQL 권건우
PgDay.Seoul
 
Logstash
琛琳 饶
 
Terraform: Infrastructure as Code
Pradeep Bhadani
 
Spark SQL Deep Dive @ Melbourne Spark Meetup
Databricks
 
PostgreSQL Deep Internal
EXEM
 
Materialized Column: An Efficient Way to Optimize Queries on Nested Columns
Databricks
 
Why does my choice of storage matter with cassandra?
Johnny Miller
 
Understanding PostgreSQL LW Locks
Jignesh Shah
 

Viewers also liked (20)

PPTX
Spring + WebSocket integration
Oleksandr Semenov
 
PPTX
Websockets and SockJS, Real time chatting
University of Alabama at Birmingham
 
ODP
SockJS Intro
Ngoc Dao
 
PDF
Realtime web application with java
JeongHun Byeon
 
PDF
Using SockJS(Websocket) with Sencha Ext JS
Kazuhiro Kotsutsumi
 
PPT
WebSockets and Java
Bozhidar Bozhanov
 
PDF
Programming WebSockets - OSCON 2010
sullis
 
PPTX
Introduction to WebSockets
WASdev Community
 
PDF
Introduction to WebSockets
Gunnar Hillert
 
PDF
Building Next Generation Real-Time Web Applications using Websockets
Naresh Chintalcheru
 
PPTX
Creating a WebSocket-Chat-Application with Jetty Embedded - Techcamp 2014
Minh Nguyen Vo Cao
 
PDF
Nuts and Bolts of WebSocket Devoxx 2014
Arun Gupta
 
PPTX
Spring Boot Update
Sergi Almar i Graupera
 
PDF
REST APIs with Spring
Joshua Long
 
PPTX
HTML5 Real-Time and Connectivity
Peter Lubbers
 
PPTX
10 performance and scalability secrets of ASP.NET websites
oazabir
 
PPTX
WebSockets in JEE 7
Shahzad Badar
 
PPTX
HTML5 Night 2014 Web x Network Technology ( WebRTC )
Kensaku Komatsu
 
PDF
Welcome to the Black Hole of Bug Bounty Program
Muneaki Nishimura
 
PDF
PhoneGap Introduction
Keisuke Todoroki
 
Spring + WebSocket integration
Oleksandr Semenov
 
Websockets and SockJS, Real time chatting
University of Alabama at Birmingham
 
SockJS Intro
Ngoc Dao
 
Realtime web application with java
JeongHun Byeon
 
Using SockJS(Websocket) with Sencha Ext JS
Kazuhiro Kotsutsumi
 
WebSockets and Java
Bozhidar Bozhanov
 
Programming WebSockets - OSCON 2010
sullis
 
Introduction to WebSockets
WASdev Community
 
Introduction to WebSockets
Gunnar Hillert
 
Building Next Generation Real-Time Web Applications using Websockets
Naresh Chintalcheru
 
Creating a WebSocket-Chat-Application with Jetty Embedded - Techcamp 2014
Minh Nguyen Vo Cao
 
Nuts and Bolts of WebSocket Devoxx 2014
Arun Gupta
 
Spring Boot Update
Sergi Almar i Graupera
 
REST APIs with Spring
Joshua Long
 
HTML5 Real-Time and Connectivity
Peter Lubbers
 
10 performance and scalability secrets of ASP.NET websites
oazabir
 
WebSockets in JEE 7
Shahzad Badar
 
HTML5 Night 2014 Web x Network Technology ( WebRTC )
Kensaku Komatsu
 
Welcome to the Black Hole of Bug Bounty Program
Muneaki Nishimura
 
PhoneGap Introduction
Keisuke Todoroki
 
Ad

Similar to WebSockets with Spring 4 (20)

PPTX
Web sockets in Java
Pance Cavkovski
 
PPTX
vlavrynovych - WebSockets Presentation
Volodymyr Lavrynovych
 
PPT
Web-Socket
Pankaj Kumar Sharma
 
PPTX
Enhancing Mobile User Experience with WebSocket
Mauricio "Maltron" Leal
 
PDF
WebSocket Push Fallback - Transcript.pdf
ShaiAlmog1
 
PPTX
HTML 5 - Web Sockets
Eyal Vardi
 
PDF
CommandBox WebSockets - and SocketBox.pdf
Ortus Solutions, Corp
 
PDF
Creating a Whatsapp Clone - Part XV - Transcript.pdf
ShaiAlmog1
 
PDF
Mulesoft Pune Meetup Deck - Apr 2020
Santosh Ojha
 
PPTX
Html5 websockets
AbhishekMondal42
 
ODP
Building Websocket Applications with GlassFish and Grizzly
Justin Lee
 
PDF
WebSocket
njamnjam
 
PDF
WebSockets - Realtime em Mundo Conectado
Bruno Borges
 
PPTX
Websocket technology for XPages
Csaba Kiss
 
PPTX
presentation in .net programming web sockets.pptx
ArvieJayLapig
 
PPTX
Websocket
Michael Jo
 
PDF
Dev con kolkata 2012 websockets
SANKARSAN BOSE
 
PPTX
Basic understanding of websocket and and REST API
divyabiru27
 
PDF
WebSockets: The Current State of the Most Valuable HTML5 API for Java Developers
Viktor Gamov
 
PPTX
Fight empire-html5
Bhakti Mehta
 
Web sockets in Java
Pance Cavkovski
 
vlavrynovych - WebSockets Presentation
Volodymyr Lavrynovych
 
Enhancing Mobile User Experience with WebSocket
Mauricio "Maltron" Leal
 
WebSocket Push Fallback - Transcript.pdf
ShaiAlmog1
 
HTML 5 - Web Sockets
Eyal Vardi
 
CommandBox WebSockets - and SocketBox.pdf
Ortus Solutions, Corp
 
Creating a Whatsapp Clone - Part XV - Transcript.pdf
ShaiAlmog1
 
Mulesoft Pune Meetup Deck - Apr 2020
Santosh Ojha
 
Html5 websockets
AbhishekMondal42
 
Building Websocket Applications with GlassFish and Grizzly
Justin Lee
 
WebSocket
njamnjam
 
WebSockets - Realtime em Mundo Conectado
Bruno Borges
 
Websocket technology for XPages
Csaba Kiss
 
presentation in .net programming web sockets.pptx
ArvieJayLapig
 
Websocket
Michael Jo
 
Dev con kolkata 2012 websockets
SANKARSAN BOSE
 
Basic understanding of websocket and and REST API
divyabiru27
 
WebSockets: The Current State of the Most Valuable HTML5 API for Java Developers
Viktor Gamov
 
Fight empire-html5
Bhakti Mehta
 
Ad

Recently uploaded (20)

PDF
Persuasive AI: risks and opportunities in the age of digital debate
Speck&Tech
 
PDF
Log-Based Anomaly Detection: Enhancing System Reliability with Machine Learning
Mohammed BEKKOUCHE
 
PPTX
Top iOS App Development Company in the USA for Innovative Apps
SynapseIndia
 
PDF
Chris Elwell Woburn, MA - Passionate About IT Innovation
Chris Elwell Woburn, MA
 
PDF
Building Real-Time Digital Twins with IBM Maximo & ArcGIS Indoors
Safe Software
 
PDF
The Builder’s Playbook - 2025 State of AI Report.pdf
jeroen339954
 
PDF
Human-centred design in online workplace learning and relationship to engagem...
Tracy Tang
 
PDF
Fl Studio 24.2.2 Build 4597 Crack for Windows Free Download 2025
faizk77g
 
PPTX
OpenID AuthZEN - Analyst Briefing July 2025
David Brossard
 
PPTX
MSP360 Backup Scheduling and Retention Best Practices.pptx
MSP360
 
PDF
LLMs.txt: Easily Control How AI Crawls Your Site
Keploy
 
PDF
SWEBOK Guide and Software Services Engineering Education
Hironori Washizaki
 
PDF
Windsurf Meetup Ottawa 2025-07-12 - Planning Mode at Reliza.pdf
Pavel Shukhman
 
PDF
HubSpot Main Hub: A Unified Growth Platform
Jaswinder Singh
 
PDF
NewMind AI - Journal 100 Insights After The 100th Issue
NewMind AI
 
PDF
CIFDAQ Weekly Market Wrap for 11th July 2025
CIFDAQ
 
PDF
Impact of IEEE Computer Society in Advancing Emerging Technologies including ...
Hironori Washizaki
 
PDF
Complete Network Protection with Real-Time Security
L4RGINDIA
 
PDF
Jak MŚP w Europie Środkowo-Wschodniej odnajdują się w świecie AI
dominikamizerska1
 
PDF
Wojciech Ciemski for Top Cyber News MAGAZINE. June 2025
Dr. Ludmila Morozova-Buss
 
Persuasive AI: risks and opportunities in the age of digital debate
Speck&Tech
 
Log-Based Anomaly Detection: Enhancing System Reliability with Machine Learning
Mohammed BEKKOUCHE
 
Top iOS App Development Company in the USA for Innovative Apps
SynapseIndia
 
Chris Elwell Woburn, MA - Passionate About IT Innovation
Chris Elwell Woburn, MA
 
Building Real-Time Digital Twins with IBM Maximo & ArcGIS Indoors
Safe Software
 
The Builder’s Playbook - 2025 State of AI Report.pdf
jeroen339954
 
Human-centred design in online workplace learning and relationship to engagem...
Tracy Tang
 
Fl Studio 24.2.2 Build 4597 Crack for Windows Free Download 2025
faizk77g
 
OpenID AuthZEN - Analyst Briefing July 2025
David Brossard
 
MSP360 Backup Scheduling and Retention Best Practices.pptx
MSP360
 
LLMs.txt: Easily Control How AI Crawls Your Site
Keploy
 
SWEBOK Guide and Software Services Engineering Education
Hironori Washizaki
 
Windsurf Meetup Ottawa 2025-07-12 - Planning Mode at Reliza.pdf
Pavel Shukhman
 
HubSpot Main Hub: A Unified Growth Platform
Jaswinder Singh
 
NewMind AI - Journal 100 Insights After The 100th Issue
NewMind AI
 
CIFDAQ Weekly Market Wrap for 11th July 2025
CIFDAQ
 
Impact of IEEE Computer Society in Advancing Emerging Technologies including ...
Hironori Washizaki
 
Complete Network Protection with Real-Time Security
L4RGINDIA
 
Jak MŚP w Europie Środkowo-Wschodniej odnajdują się w świecie AI
dominikamizerska1
 
Wojciech Ciemski for Top Cyber News MAGAZINE. June 2025
Dr. Ludmila Morozova-Buss
 

WebSockets with Spring 4

  • 1. WebSockets with Spring 4 Sergi Almar @sergialmar
  • 2. Who I am • CTO @ Voz.io • Spring Certified Trainer • javaHispano Core Member • Spring I/O conference organiser
  • 3. Collaborative Apps Multiplayer Games Multimedia Chat Social Feeds Sports Updates Financial Tickets Clickstream Data Online Education Location-based Apps
  • 4. Real-Time Data on the Web • Polling • Long Polling / Comet • Flash
  • 5. Problem Applications need two-way communication Too many connections and overhead with ajax / comet
  • 7. WebSocket Protocol / RFC 6455 • Real-time full duplex communication over TCP • Uses port 80 / 443 (URL scheme: ws:// and wss://) • Small overhead for text messages (frames) • • 0x00 for frame start, 0xFF for frame end (vs HTTP 1Kb) Ping / pong frames for staying alive
  • 8. WebSocket Handshake 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! client sends a WebSocket handshake request HTTP/1.1 101 Switching Protocols! Upgrade: websocket! Connection: Upgrade! Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=! Sec-WebSocket-Protocol: chat! server response
  • 9. JS WebSocket API var ws = new WebSocket("ws://www.java2days.com/ws");! ! // When the connection is open, send some data to the server! ws.onopen = function () {! ws.send('Here I am!');! };! ! // Log messages from the server! ws.onmessage = function (event) {! console.log('message: ' + event.data);! };! ! ws.onclose = function (event) {! console.log('closed:' + event.code);! };!
  • 10. Java WebSocket Implementations • Multiple implementations before the standard • JSR-356 (May 2013) • Reference implementation Tyrus (bundled with Glassfish 4) • Rewrite across containers (tomcat 8.0.0-RC5, Jetty 9.1…)
  • 12. Spring WebSockets • WebSockets are now supported in Spring 4 • Fallback options with SockJS • STOMP over WebSocket • Foundation for messaging architecture
  • 13. WebSocket Handlers public class EchoHandler extends TextWebSocketHandlerAdapter {! ! @Override! public void handleTextMessage(WebSocketSession session, ! ! ! ! ! ! ! ! ! ! ! TextMessage message) throws Exception {! session.sendMessage(message);! }! ! }
  • 14. WebSocket Config @Configuration! @EnableWebSocket! public class WsConfig implements WebSocketConfigurer {! ! ! ! @Override! public void registerWebSocketHandlers(! ! ! ! ! ! ! ! ! ! WebSocketHandlerRegistry registry) {! ! registry.addHandler(new EchoHandler(), "/echo");! }! }!
  • 15. Per-Session Handler Previous example showed how to configure a global handler • • but you may want to have a stateful per-session handler @Configuration! @EnableWebSocket! public class WsConfig implements WebSocketConfigurer {! ! ! @Bean! DI public WebSocketHandler echoHandler() {! return new PerConnectionWebSocketHandler(EchoHandler.class);! }! @Override! public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {! registry.addHandler(echoHandler(), "/echo");! }! }
  • 16. Can anyone join the party? http://caniuse.com/#feat=websockets / DEC 2013
  • 18. SockJS • Coherent, cross-browser, Javascript API for full duplex communication. • Close to HTML5 WebSockets API • Client and server side implementation (ruby, node… and also in spring-websockets)
  • 19. SocksJS API var sock = new SockJS('http://www.java2days.com/ws');! ! sock.onopen = function() {! sock.send('Here I am'); };! ! ! sock.onmessage = function(event) {! console.log('message', e.data);! };! ! sock.onclose = function() {! console.log('close');! };!
  • 20. SockJS URLs • Base URL: /base_url • Info test: /base_url/info • Session URL: /base_url/server/session
  • 21. Enabling SocksJS @Configuration! @EnableWebSocket! public class WsConfig implements WebSocketConfigurer {! ! ! ! @Override! public void registerWebSocketHandlers(! ! ! ! ! ! ! ! ! ! WebSocketHandlerRegistry registry) {! ! registry.addHandler(new EchoHandler(), “/echo”).withSockJS();! }! }! MessageHandler doesn’t change (SocketJsService delivers the message to the handler regardless of the protocol)
  • 22. Problem • WebSockets are too low level and different from HTTP / REST • We need asynchronous, event-driven, reactive programming style • Mmmm, that sounds familiar: JMS, AMQP… 
 but we still want to stick to the Spring MVC programming model
  • 24. …but we want something like this
  • 25. Solution • Stomp over WebSocket • Some Spring Integration types have been promoted to the core • • • Message, MessageChannel, MessageHandler… @MessageMapping, @SubscribeEvent… New spring-messaging module
  • 26. STOMP
  • 27. STOMP • Simple interoperable protocol for asynchronous messaging • Supported by Apache ActiveMQ, RabbitMQ, HornetQ… • Frames modelled on HTTP var socket = new SockJS('/myapp/echo');! var client = Stomp.over(socket); COMMAND! header1:value1! header2:value2! ! Body^@!
  • 28. Client Frames • SEND a message • SUBSCRIBE / UNSUBSCRIBE from destination • ACK / NACK the reception of a message (optional by default)
  • 29. Server Frames • Convey a MESSAGE from subscription to the client • Send RECEIPT when server has successfully processed a client frame • Send an ERROR if something goes wrong
  • 30. Configuration ! @Configuration! @EnableWebSocketMessageBroker! public class Config implements WebSocketMessageBrokerConfigurer {! ! @Override! public void registerStompEndpoints(StompEndpointRegistry r){! r.addEndpoint("/stomp");! }! ! @Override! public void configureMessageBroker(MessageBrokerConfigurer c){! c.enableSimpleBroker("/topic/");! Subscriptions c.setApplicationDestinationPrefixes("/app");! processed by spring }! ! }! simple broker
  • 31. Sending Messages stomp.js stompClient.send("/app/trade", {}, JSON.stringify(trade)); prefix SEND! destination:/app/trade! content-type:application/json! content-length:47! ! {"action":"Sell","ticker":"DELL","shares":"10"}! supports ant-style patterns @MessageMapping("/trade")! public void executeTrade(Trade trade, Principal principal) {! ! trade.setUsername(principal.getName());! ! this.tradeService.executeTrade(trade);! }
  • 32. Handler Methods • Flexible handler method signatures • @PathVariable, @Header/@Headers, @Payload, Message, Principal • Message converters @Controller! public class ChatController {! ! @MessageMapping("/message")! public void sendMessage(String message, Principal principal) {! // ...! }! }!
  • 33. Handler Methods • Can also return a value ! ! ! Return wrapped in a Message and sent to /topic/message @MessageMapping("/message")! public String sendMessage(String message) {! return message.toUpperCase();! } ! • Or define the destination with @SendTo @MessageMapping("/message")! @SendTo("/topic/spring-room")! public String sendMessage(String message) {! return message.toUpperCase();! }!
  • 34. Intercepting Subscriptions stompClient.subscribe("/app/positions", function(message) {! ...! });! SUBSCRIBE! id:sub-0! destination:/app/positions! @Controller! public class PortfolioController {! ! @SubscribeEvent("/positions")! public List<Position> getPositions(Principal p) {! Portfolio portfolio = ...! return portfolio.getPositions();! }! } sent directly to the client, not going though the message broker
  • 35. User destinations • User specific queues can be used • • • /user/** kind of paths queues with unique id will be created Useful to send user related information or errors client.subscribe("/user/queue/private-messages", function(msg) {! // ...! });! ! client.subscribe("/user/queue/errors", function(msg) {! // ...! });!
  • 36. Sending to user @Controller! public class ChatController {! Will be sent to /user/{username}/queue/message ! @MessageMapping("/message")! @SendToUser! public String sendMessage(String message) {! return message.toUpperCase();! }! ! @MessageExceptionHandler! @SendToUser("/queue/errors")! public String handleException(IllegalStateException ex) {! return ex.getMessage();! }! ! }!
  • 37. SimpMessagingTemplate • Sending messages without handler methods template.convertAndSend("/topic/chat", message;! template.convertAndSendToUser(user, dest, message;
  • 38. Using a Message Broker • Previous configuration used Spring’s simple broker • • • Not suitable for clustering Subset of STOMP A message broker can be plugged-in instead
  • 39. Message Broker Config @Configuration! @EnableWebSocketMessageBroker! public class Config implements WebSocketMessageBrokerConfigurer{! ! @Override! public void configureMessageBroker(MessageBrokerConfigurer c){! c.enableStompBrokerRelay("/queue/", "/topic/");! c.setApplicationDestinationPrefixes("/app");! }! }