SlideShare a Scribd company logo
Creating a WhatsApp Clone - Part XV
Next we’ll jump to the websocket package which is the last package
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Bean
public ServletServerContainerFactoryBean createWebSocketContainer() {
ServletServerContainerFactoryBean container =
new ServletServerContainerFactoryBean();
container.setMaxTextMessageBufferSize(8192);
container.setMaxBinaryMessageBufferSize(8192);
return container;
}
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry
registry) {
registry.addHandler(myHandler(), "/socket");
}
@Bean
public WebSocketHandler myHandler() {
AppSocket
First we need to configure the web socket.

We do this by implementing the WebSocketConfigurer and using the annotations on the class to indicate its purpose
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Bean
public ServletServerContainerFactoryBean createWebSocketContainer() {
ServletServerContainerFactoryBean container =
new ServletServerContainerFactoryBean();
container.setMaxTextMessageBufferSize(8192);
container.setMaxBinaryMessageBufferSize(8192);
return container;
}
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry
registry) {
registry.addHandler(myHandler(), "/socket");
}
@Bean
public WebSocketHandler myHandler() {
AppSocket
We define the socket so we can define the packet size to 8kb. We can set a larger size but generally keeping packets small is a good practice
public ServletServerContainerFactoryBean createWebSocketContainer() {
ServletServerContainerFactoryBean container =
new ServletServerContainerFactoryBean();
container.setMaxTextMessageBufferSize(8192);
container.setMaxBinaryMessageBufferSize(8192);
return container;
}
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry
registry) {
registry.addHandler(myHandler(), "/socket");
}
@Bean
public WebSocketHandler myHandler() {
return new AppSocket();
}
@Bean
public TaskScheduler taskScheduler() {
return new ConcurrentTaskScheduler(Executors.
newSingleThreadScheduledExecutor());
}
AppSocket
The AppSocket class is bound to the /socket URL in this line of code
container.setMaxTextMessageBufferSize(8192);
container.setMaxBinaryMessageBufferSize(8192);
return container;
}
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry
registry) {
registry.addHandler(myHandler(), "/socket");
}
@Bean
public WebSocketHandler myHandler() {
return new AppSocket();
}
@Bean
public TaskScheduler taskScheduler() {
return new ConcurrentTaskScheduler(Executors.
newSingleThreadScheduledExecutor());
}
}
AppSocket
This is the thread used to process the websocket connections. We can allocate more thread resources based on need
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
public class AppSocket extends TextWebSocketHandler {
private static Logger log =
Logger.getLogger(AppSocket.class.getName());
private static final Map<String, List<WebSocketSession>> clients =
new HashMap<>();
@Autowired
private UserService users;
private static boolean sendToToken(String token, String json) {
List<WebSocketSession> ws = clients.get(token);
WebSocketSession currentSocket = null;
try {
if(ws != null) {
TextMessage t = new TextMessage(json);
List<WebSocketSession> removeQueue = null;
for(WebSocketSession w : ws) {
currentSocket = w;
if(currentSocket.isOpen()) {
AppSocket
Next lets go to AppSocket

The app socket is an implementation of TextWebSocketHandler which handles text messages. Since all our messages are JSON this makes more sense.
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
public class AppSocket extends TextWebSocketHandler {
private static Logger log =
Logger.getLogger(AppSocket.class.getName());
private static final Map<String, List<WebSocketSession>> clients =
new HashMap<>();
@Autowired
private UserService users;
private static boolean sendToToken(String token, String json) {
List<WebSocketSession> ws = clients.get(token);
WebSocketSession currentSocket = null;
try {
if(ws != null) {
TextMessage t = new TextMessage(json);
List<WebSocketSession> removeQueue = null;
for(WebSocketSession w : ws) {
currentSocket = w;
if(currentSocket.isOpen()) {
AppSocket
I cache the currently active connections here. This isn’t a good approach in the long term. A better approach would be redis for this sort of caching. But for an initial app
this can work fine
public class AppSocket extends TextWebSocketHandler {
private static Logger log =
Logger.getLogger(AppSocket.class.getName());
private static final Map<String, List<WebSocketSession>> clients =
new HashMap<>();
@Autowired
private UserService users;
private static boolean sendToToken(String token, String json) {
List<WebSocketSession> ws = clients.get(token);
WebSocketSession currentSocket = null;
try {
if(ws != null) {
TextMessage t = new TextMessage(json);
List<WebSocketSession> removeQueue = null;
for(WebSocketSession w : ws) {
currentSocket = w;
if(currentSocket.isOpen()) {
w.sendMessage(t);
return true;
AppSocket
We need access to the UsersService so we can send a message to a group or user.
private static final Map<String, List<WebSocketSession>> clients =
new HashMap<>();
@Autowired
private UserService users;
private static boolean sendToToken(String token, String json) {
List<WebSocketSession> ws = clients.get(token);
WebSocketSession currentSocket = null;
try {
if(ws != null) {
TextMessage t = new TextMessage(json);
List<WebSocketSession> removeQueue = null;
for(WebSocketSession w : ws) {
currentSocket = w;
if(currentSocket.isOpen()) {
w.sendMessage(t);
return true;
} else {
if(removeQueue == null) {
removeQueue = new ArrayList<>();
}
removeQueue.add(w);
}
AppSocket
This method sends JSON to a websocket based on the user token and returns true if it succeeded.
private static final Map<String, List<WebSocketSession>> clients =
new HashMap<>();
@Autowired
private UserService users;
private static boolean sendToToken(String token, String json) {
List<WebSocketSession> ws = clients.get(token);
WebSocketSession currentSocket = null;
try {
if(ws != null) {
TextMessage t = new TextMessage(json);
List<WebSocketSession> removeQueue = null;
for(WebSocketSession w : ws) {
currentSocket = w;
if(currentSocket.isOpen()) {
w.sendMessage(t);
return true;
} else {
if(removeQueue == null) {
removeQueue = new ArrayList<>();
}
removeQueue.add(w);
}
AppSocket
We get the sessions for the given client
private static boolean sendToToken(String token, String json) {
List<WebSocketSession> ws = clients.get(token);
WebSocketSession currentSocket = null;
try {
if(ws != null) {
TextMessage t = new TextMessage(json);
List<WebSocketSession> removeQueue = null;
for(WebSocketSession w : ws) {
currentSocket = w;
if(currentSocket.isOpen()) {
w.sendMessage(t);
return true;
} else {
if(removeQueue == null) {
removeQueue = new ArrayList<>();
}
removeQueue.add(w);
}
}
if(removeQueue != null) {
for(WebSocketSession w : removeQueue) {
ws.remove(w);
}
AppSocket
If he has a webservice sessions
private static boolean sendToToken(String token, String json) {
List<WebSocketSession> ws = clients.get(token);
WebSocketSession currentSocket = null;
try {
if(ws != null) {
TextMessage t = new TextMessage(json);
List<WebSocketSession> removeQueue = null;
for(WebSocketSession w : ws) {
currentSocket = w;
if(currentSocket.isOpen()) {
w.sendMessage(t);
return true;
} else {
if(removeQueue == null) {
removeQueue = new ArrayList<>();
}
removeQueue.add(w);
}
}
if(removeQueue != null) {
for(WebSocketSession w : removeQueue) {
ws.remove(w);
}
AppSocket
We create a text message with the JSON
List<WebSocketSession> ws = clients.get(token);
WebSocketSession currentSocket = null;
try {
if(ws != null) {
TextMessage t = new TextMessage(json);
List<WebSocketSession> removeQueue = null;
for(WebSocketSession w : ws) {
currentSocket = w;
if(currentSocket.isOpen()) {
w.sendMessage(t);
return true;
} else {
if(removeQueue == null) {
removeQueue = new ArrayList<>();
}
removeQueue.add(w);
}
}
if(removeQueue != null) {
for(WebSocketSession w : removeQueue) {
ws.remove(w);
}
}
} else {
AppSocket
We loop over all the websocket connections one by one
List<WebSocketSession> ws = clients.get(token);
WebSocketSession currentSocket = null;
try {
if(ws != null) {
TextMessage t = new TextMessage(json);
List<WebSocketSession> removeQueue = null;
for(WebSocketSession w : ws) {
currentSocket = w;
if(currentSocket.isOpen()) {
w.sendMessage(t);
return true;
} else {
if(removeQueue == null) {
removeQueue = new ArrayList<>();
}
removeQueue.add(w);
}
}
if(removeQueue != null) {
for(WebSocketSession w : removeQueue) {
ws.remove(w);
}
}
} else {
AppSocket
If a connection is open we send the message there and return
List<WebSocketSession> ws = clients.get(token);
WebSocketSession currentSocket = null;
try {
if(ws != null) {
TextMessage t = new TextMessage(json);
List<WebSocketSession> removeQueue = null;
for(WebSocketSession w : ws) {
currentSocket = w;
if(currentSocket.isOpen()) {
w.sendMessage(t);
return true;
} else {
if(removeQueue == null) {
removeQueue = new ArrayList<>();
}
removeQueue.add(w);
}
}
if(removeQueue != null) {
for(WebSocketSession w : removeQueue) {
ws.remove(w);
}
}
} else {
AppSocket
Otherwise we add the socket to the remove queue. We don’t want to remove in the middle of the loop to prevent an exception.
if(removeQueue == null) {
removeQueue = new ArrayList<>();
}
removeQueue.add(w);
}
}
if(removeQueue != null) {
for(WebSocketSession w : removeQueue) {
ws.remove(w);
}
}
} else {
log.warning("No WS connections for token: " + token);
}
} catch(IOException err) {
log.log(Level.SEVERE, "Exception during sending message", err);
if(currentSocket != null && ws != null) {
ws.remove(currentSocket);
if(ws.isEmpty()) {
clients.remove(token);
}
}
}
return false;
AppSocket
We remove all the defunct websockets from the queue in this line
removeQueue.add(w);
}
}
if(removeQueue != null) {
for(WebSocketSession w : removeQueue) {
ws.remove(w);
}
}
} else {
log.warning("No WS connections for token: " + token);
}
} catch(IOException err) {
log.log(Level.SEVERE, "Exception during sending message", err);
if(currentSocket != null && ws != null) {
ws.remove(currentSocket);
if(ws.isEmpty()) {
clients.remove(token);
}
}
}
return false;
}
public static void sendUserTyping(String token, String id,
AppSocket
For all the cases where sending via the socket didn't work we return false
"","authorId":"" + id + ""}");
}
public static boolean sendMessage(String token, String json) {
return sendToToken(token, json);
}
@Override
protected void handleTextMessage(WebSocketSession session,
TextMessage message) throws Exception {
JsonParser parser = JsonParserFactory.getJsonParser();
Map<String, Object> m = parser.parseMap(message.getPayload());
String type = (String)m.get("t");
if(type != null) {
if(type.equals("init")) {
String token = (String)m.get("tok");
Number time = (Number)m.get("time");
List<WebSocketSession> l = clients.get(token);
if(l == null) {
l = new ArrayList<>();
clients.put(token, l);
}
l.add(session);
return;
AppSocket
This method handles the incoming text packets
public static boolean sendMessage(String token, String json) {
return sendToToken(token, json);
}
@Override
protected void handleTextMessage(WebSocketSession session,
TextMessage message) throws Exception {
JsonParser parser = JsonParserFactory.getJsonParser();
Map<String, Object> m = parser.parseMap(message.getPayload());
String type = (String)m.get("t");
if(type != null) {
if(type.equals("init")) {
String token = (String)m.get("tok");
Number time = (Number)m.get("time");
List<WebSocketSession> l = clients.get(token);
if(l == null) {
l = new ArrayList<>();
clients.put(token, l);
}
l.add(session);
return;
}
} else {
String typing = (String)m.get("typing");
AppSocket
First we need to parse the JSON into a map
@Override
protected void handleTextMessage(WebSocketSession session,
TextMessage message) throws Exception {
JsonParser parser = JsonParserFactory.getJsonParser();
Map<String, Object> m = parser.parseMap(message.getPayload());
String type = (String)m.get("t");
if(type != null) {
if(type.equals("init")) {
String token = (String)m.get("tok");
Number time = (Number)m.get("time");
List<WebSocketSession> l = clients.get(token);
if(l == null) {
l = new ArrayList<>();
clients.put(token, l);
}
l.add(session);
return;
}
} else {
String typing = (String)m.get("typing");
String sentTo = (String)m.get("sentTo");
if(typing != null) {
String authorId = (String)m.get("authorId");
users.userTyping(authorId, sentTo, true);
AppSocket
If a message has a type it’s probably an init message
@Override
protected void handleTextMessage(WebSocketSession session,
TextMessage message) throws Exception {
JsonParser parser = JsonParserFactory.getJsonParser();
Map<String, Object> m = parser.parseMap(message.getPayload());
String type = (String)m.get("t");
if(type != null) {
if(type.equals("init")) {
String token = (String)m.get("tok");
Number time = (Number)m.get("time");
List<WebSocketSession> l = clients.get(token);
if(l == null) {
l = new ArrayList<>();
clients.put(token, l);
}
l.add(session);
return;
}
} else {
String typing = (String)m.get("typing");
String sentTo = (String)m.get("sentTo");
if(typing != null) {
String authorId = (String)m.get("authorId");
users.userTyping(authorId, sentTo, true);
AppSocket
init messages allow us to add a websocket to our cache of connections so we can push a message back into the websocket when we need to send a server notification
l = new ArrayList<>();
clients.put(token, l);
}
l.add(session);
return;
}
} else {
String typing = (String)m.get("typing");
String sentTo = (String)m.get("sentTo");
if(typing != null) {
String authorId = (String)m.get("authorId");
users.userTyping(authorId, sentTo, true);
} else {
String id = (String)m.get("id");
if(id == null) {
users.sendMessage(sentTo, m);
} else {
users.sendJSONTo(sentTo, message.getPayload());
}
}
}
}
AppSocket
Otherwise we test if this is a “user typing" event in which case we send a typing message onward
l = new ArrayList<>();
clients.put(token, l);
}
l.add(session);
return;
}
} else {
String typing = (String)m.get("typing");
String sentTo = (String)m.get("sentTo");
if(typing != null) {
String authorId = (String)m.get("authorId");
users.userTyping(authorId, sentTo, true);
} else {
String id = (String)m.get("id");
if(id == null) {
users.sendMessage(sentTo, m);
} else {
users.sendJSONTo(sentTo, message.getPayload());
}
}
}
}
AppSocket
Finally we send the message as JSON to the users in the group or the specific user. This invokes the code we saw in the user service class
@Override
public void handleTransportError(WebSocketSession wss,
Throwable thrwbl) throws Exception {
log.log(Level.SEVERE, "Error during transport", thrwbl);
}
@Override
public void afterConnectionClosed(WebSocketSession wss, CloseStatus cs)
throws Exception {
for(String s : clients.keySet()) {
List<WebSocketSession> wl = clients.get(s);
for(WebSocketSession w : wl) {
if(w == wss) {
wl.remove(w);
if(wl.isEmpty()) {
clients.remove(s);
}
return;
}
}
}
}
AppSocket
When a connection is closed we loop over the existing list and purge it of the dead connection
@Override
public void afterConnectionClosed(WebSocketSession wss, CloseStatus cs)
throws Exception {
for(String s : clients.keySet()) {
List<WebSocketSession> wl = clients.get(s);
for(WebSocketSession w : wl) {
if(w == wss) {
wl.remove(w);
if(wl.isEmpty()) {
clients.remove(s);
}
return;
}
}
}
}
@Override
public boolean supportsPartialMessages() {
return false;
}
}
AppSocket
For simplicity we don't support partial messages which shouldn’t be necessary for small 8kb messages. With that the class is done

More Related Content

Similar to Creating a Whatsapp Clone - Part XV - Transcript.pdf

Mobile Software Engineering Crash Course - C06 WindowsPhone
Mobile Software Engineering Crash Course - C06 WindowsPhoneMobile Software Engineering Crash Course - C06 WindowsPhone
Mobile Software Engineering Crash Course - C06 WindowsPhone
Mohammad Shaker
 
Creating the interfaces of the future with the APIs of today
Creating the interfaces of the future with the APIs of todayCreating the interfaces of the future with the APIs of today
Creating the interfaces of the future with the APIs of today
gerbille
 
Correcting Common Async Await Mistakes in .NET
Correcting Common Async Await Mistakes in .NET Correcting Common Async Await Mistakes in .NET
Correcting Common Async Await Mistakes in .NET
Brandon Minnick, MBA
 
Workshop: Async and Parallel in C#
Workshop: Async and Parallel in C#Workshop: Async and Parallel in C#
Workshop: Async and Parallel in C#
Rainer Stropek
 
Speed up your Web applications with HTML5 WebSockets
Speed up your Web applications with HTML5 WebSocketsSpeed up your Web applications with HTML5 WebSockets
Speed up your Web applications with HTML5 WebSockets
Yakov Fain
 
Qt & Webkit
Qt & WebkitQt & Webkit
Qt & Webkit
QT-day
 
20240516_동적_데이터을_대응하는_코드_작성하기.pdf
20240516_동적_데이터을_대응하는_코드_작성하기.pdf20240516_동적_데이터을_대응하는_코드_작성하기.pdf
20240516_동적_데이터을_대응하는_코드_작성하기.pdf
정민 안
 
4Developers 2018: Real-time capabilities in ASP.NET Core web applications (To...
4Developers 2018: Real-time capabilities in ASP.NET Core web applications (To...4Developers 2018: Real-time capabilities in ASP.NET Core web applications (To...
4Developers 2018: Real-time capabilities in ASP.NET Core web applications (To...
PROIDEA
 
JavaScript Lessons 2023
JavaScript Lessons 2023JavaScript Lessons 2023
JavaScript Lessons 2023
Laurence Svekis ✔
 
Correcting Common Async/Await Mistakes in .NET
Correcting Common Async/Await Mistakes in .NETCorrecting Common Async/Await Mistakes in .NET
Correcting Common Async/Await Mistakes in .NET
Brandon Minnick, MBA
 
Implement react pagination with react hooks and react paginate
Implement react pagination with react hooks and react paginateImplement react pagination with react hooks and react paginate
Implement react pagination with react hooks and react paginate
Katy Slemon
 
[JEEConf-2017] RxJava as a key component in mature Big Data product
[JEEConf-2017] RxJava as a key component in mature Big Data product[JEEConf-2017] RxJava as a key component in mature Big Data product
[JEEConf-2017] RxJava as a key component in mature Big Data product
Igor Lozynskyi
 
Websockets talk at Rubyconf Uruguay 2010
Websockets talk at Rubyconf Uruguay 2010Websockets talk at Rubyconf Uruguay 2010
Websockets talk at Rubyconf Uruguay 2010
Ismael Celis
 
Building interactivity with websockets
Building interactivity with websocketsBuilding interactivity with websockets
Building interactivity with websockets
Wim Godden
 
Mobile Web 5.0
Mobile Web 5.0Mobile Web 5.0
Mobile Web 5.0
Michael Galpin
 
Wonderful csom sps barcelona
Wonderful csom sps barcelonaWonderful csom sps barcelona
Wonderful csom sps barcelona
Sonja Madsen
 
Correcting Common .NET Async/Await Mistakes
Correcting Common .NET Async/Await MistakesCorrecting Common .NET Async/Await Mistakes
Correcting Common .NET Async/Await Mistakes
Brandon Minnick, MBA
 
The First Contact with Java EE 7
The First Contact with Java EE 7The First Contact with Java EE 7
The First Contact with Java EE 7
Roberto Cortez
 
Unity and WebSockets
Unity and WebSocketsUnity and WebSockets
Unity and WebSockets
Josh Glover
 
Modern Android app library stack
Modern Android app library stackModern Android app library stack
Modern Android app library stack
Tomáš Kypta
 

Similar to Creating a Whatsapp Clone - Part XV - Transcript.pdf (20)

Mobile Software Engineering Crash Course - C06 WindowsPhone
Mobile Software Engineering Crash Course - C06 WindowsPhoneMobile Software Engineering Crash Course - C06 WindowsPhone
Mobile Software Engineering Crash Course - C06 WindowsPhone
 
Creating the interfaces of the future with the APIs of today
Creating the interfaces of the future with the APIs of todayCreating the interfaces of the future with the APIs of today
Creating the interfaces of the future with the APIs of today
 
Correcting Common Async Await Mistakes in .NET
Correcting Common Async Await Mistakes in .NET Correcting Common Async Await Mistakes in .NET
Correcting Common Async Await Mistakes in .NET
 
Workshop: Async and Parallel in C#
Workshop: Async and Parallel in C#Workshop: Async and Parallel in C#
Workshop: Async and Parallel in C#
 
Speed up your Web applications with HTML5 WebSockets
Speed up your Web applications with HTML5 WebSocketsSpeed up your Web applications with HTML5 WebSockets
Speed up your Web applications with HTML5 WebSockets
 
Qt & Webkit
Qt & WebkitQt & Webkit
Qt & Webkit
 
20240516_동적_데이터을_대응하는_코드_작성하기.pdf
20240516_동적_데이터을_대응하는_코드_작성하기.pdf20240516_동적_데이터을_대응하는_코드_작성하기.pdf
20240516_동적_데이터을_대응하는_코드_작성하기.pdf
 
4Developers 2018: Real-time capabilities in ASP.NET Core web applications (To...
4Developers 2018: Real-time capabilities in ASP.NET Core web applications (To...4Developers 2018: Real-time capabilities in ASP.NET Core web applications (To...
4Developers 2018: Real-time capabilities in ASP.NET Core web applications (To...
 
JavaScript Lessons 2023
JavaScript Lessons 2023JavaScript Lessons 2023
JavaScript Lessons 2023
 
Correcting Common Async/Await Mistakes in .NET
Correcting Common Async/Await Mistakes in .NETCorrecting Common Async/Await Mistakes in .NET
Correcting Common Async/Await Mistakes in .NET
 
Implement react pagination with react hooks and react paginate
Implement react pagination with react hooks and react paginateImplement react pagination with react hooks and react paginate
Implement react pagination with react hooks and react paginate
 
[JEEConf-2017] RxJava as a key component in mature Big Data product
[JEEConf-2017] RxJava as a key component in mature Big Data product[JEEConf-2017] RxJava as a key component in mature Big Data product
[JEEConf-2017] RxJava as a key component in mature Big Data product
 
Websockets talk at Rubyconf Uruguay 2010
Websockets talk at Rubyconf Uruguay 2010Websockets talk at Rubyconf Uruguay 2010
Websockets talk at Rubyconf Uruguay 2010
 
Building interactivity with websockets
Building interactivity with websocketsBuilding interactivity with websockets
Building interactivity with websockets
 
Mobile Web 5.0
Mobile Web 5.0Mobile Web 5.0
Mobile Web 5.0
 
Wonderful csom sps barcelona
Wonderful csom sps barcelonaWonderful csom sps barcelona
Wonderful csom sps barcelona
 
Correcting Common .NET Async/Await Mistakes
Correcting Common .NET Async/Await MistakesCorrecting Common .NET Async/Await Mistakes
Correcting Common .NET Async/Await Mistakes
 
The First Contact with Java EE 7
The First Contact with Java EE 7The First Contact with Java EE 7
The First Contact with Java EE 7
 
Unity and WebSockets
Unity and WebSocketsUnity and WebSockets
Unity and WebSockets
 
Modern Android app library stack
Modern Android app library stackModern Android app library stack
Modern Android app library stack
 

More from ShaiAlmog1

The Duck Teaches Learn to debug from the masters. Local to production- kill ...
The Duck Teaches  Learn to debug from the masters. Local to production- kill ...The Duck Teaches  Learn to debug from the masters. Local to production- kill ...
The Duck Teaches Learn to debug from the masters. Local to production- kill ...
ShaiAlmog1
 
create-netflix-clone-06-client-ui.pdf
create-netflix-clone-06-client-ui.pdfcreate-netflix-clone-06-client-ui.pdf
create-netflix-clone-06-client-ui.pdf
ShaiAlmog1
 
create-netflix-clone-01-introduction_transcript.pdf
create-netflix-clone-01-introduction_transcript.pdfcreate-netflix-clone-01-introduction_transcript.pdf
create-netflix-clone-01-introduction_transcript.pdf
ShaiAlmog1
 
create-netflix-clone-02-server_transcript.pdf
create-netflix-clone-02-server_transcript.pdfcreate-netflix-clone-02-server_transcript.pdf
create-netflix-clone-02-server_transcript.pdf
ShaiAlmog1
 
create-netflix-clone-04-server-continued_transcript.pdf
create-netflix-clone-04-server-continued_transcript.pdfcreate-netflix-clone-04-server-continued_transcript.pdf
create-netflix-clone-04-server-continued_transcript.pdf
ShaiAlmog1
 
create-netflix-clone-01-introduction.pdf
create-netflix-clone-01-introduction.pdfcreate-netflix-clone-01-introduction.pdf
create-netflix-clone-01-introduction.pdf
ShaiAlmog1
 
create-netflix-clone-06-client-ui_transcript.pdf
create-netflix-clone-06-client-ui_transcript.pdfcreate-netflix-clone-06-client-ui_transcript.pdf
create-netflix-clone-06-client-ui_transcript.pdf
ShaiAlmog1
 
create-netflix-clone-03-server.pdf
create-netflix-clone-03-server.pdfcreate-netflix-clone-03-server.pdf
create-netflix-clone-03-server.pdf
ShaiAlmog1
 
create-netflix-clone-04-server-continued.pdf
create-netflix-clone-04-server-continued.pdfcreate-netflix-clone-04-server-continued.pdf
create-netflix-clone-04-server-continued.pdf
ShaiAlmog1
 
create-netflix-clone-05-client-model_transcript.pdf
create-netflix-clone-05-client-model_transcript.pdfcreate-netflix-clone-05-client-model_transcript.pdf
create-netflix-clone-05-client-model_transcript.pdf
ShaiAlmog1
 
create-netflix-clone-03-server_transcript.pdf
create-netflix-clone-03-server_transcript.pdfcreate-netflix-clone-03-server_transcript.pdf
create-netflix-clone-03-server_transcript.pdf
ShaiAlmog1
 
create-netflix-clone-02-server.pdf
create-netflix-clone-02-server.pdfcreate-netflix-clone-02-server.pdf
create-netflix-clone-02-server.pdf
ShaiAlmog1
 
create-netflix-clone-05-client-model.pdf
create-netflix-clone-05-client-model.pdfcreate-netflix-clone-05-client-model.pdf
create-netflix-clone-05-client-model.pdf
ShaiAlmog1
 
Creating a Whatsapp Clone - Part IX - Transcript.pdf
Creating a Whatsapp Clone - Part IX - Transcript.pdfCreating a Whatsapp Clone - Part IX - Transcript.pdf
Creating a Whatsapp Clone - Part IX - Transcript.pdf
ShaiAlmog1
 
Creating a Whatsapp Clone - Part V - Transcript.pdf
Creating a Whatsapp Clone - Part V - Transcript.pdfCreating a Whatsapp Clone - Part V - Transcript.pdf
Creating a Whatsapp Clone - Part V - Transcript.pdf
ShaiAlmog1
 
Creating a Whatsapp Clone - Part IV - Transcript.pdf
Creating a Whatsapp Clone - Part IV - Transcript.pdfCreating a Whatsapp Clone - Part IV - Transcript.pdf
Creating a Whatsapp Clone - Part IV - Transcript.pdf
ShaiAlmog1
 
Creating a Whatsapp Clone - Part IV.pdf
Creating a Whatsapp Clone - Part IV.pdfCreating a Whatsapp Clone - Part IV.pdf
Creating a Whatsapp Clone - Part IV.pdf
ShaiAlmog1
 
Creating a Whatsapp Clone - Part I - Transcript.pdf
Creating a Whatsapp Clone - Part I - Transcript.pdfCreating a Whatsapp Clone - Part I - Transcript.pdf
Creating a Whatsapp Clone - Part I - Transcript.pdf
ShaiAlmog1
 
Creating a Whatsapp Clone - Part IX.pdf
Creating a Whatsapp Clone - Part IX.pdfCreating a Whatsapp Clone - Part IX.pdf
Creating a Whatsapp Clone - Part IX.pdf
ShaiAlmog1
 
Creating a Whatsapp Clone - Part VI.pdf
Creating a Whatsapp Clone - Part VI.pdfCreating a Whatsapp Clone - Part VI.pdf
Creating a Whatsapp Clone - Part VI.pdf
ShaiAlmog1
 

More from ShaiAlmog1 (20)

The Duck Teaches Learn to debug from the masters. Local to production- kill ...
The Duck Teaches  Learn to debug from the masters. Local to production- kill ...The Duck Teaches  Learn to debug from the masters. Local to production- kill ...
The Duck Teaches Learn to debug from the masters. Local to production- kill ...
 
create-netflix-clone-06-client-ui.pdf
create-netflix-clone-06-client-ui.pdfcreate-netflix-clone-06-client-ui.pdf
create-netflix-clone-06-client-ui.pdf
 
create-netflix-clone-01-introduction_transcript.pdf
create-netflix-clone-01-introduction_transcript.pdfcreate-netflix-clone-01-introduction_transcript.pdf
create-netflix-clone-01-introduction_transcript.pdf
 
create-netflix-clone-02-server_transcript.pdf
create-netflix-clone-02-server_transcript.pdfcreate-netflix-clone-02-server_transcript.pdf
create-netflix-clone-02-server_transcript.pdf
 
create-netflix-clone-04-server-continued_transcript.pdf
create-netflix-clone-04-server-continued_transcript.pdfcreate-netflix-clone-04-server-continued_transcript.pdf
create-netflix-clone-04-server-continued_transcript.pdf
 
create-netflix-clone-01-introduction.pdf
create-netflix-clone-01-introduction.pdfcreate-netflix-clone-01-introduction.pdf
create-netflix-clone-01-introduction.pdf
 
create-netflix-clone-06-client-ui_transcript.pdf
create-netflix-clone-06-client-ui_transcript.pdfcreate-netflix-clone-06-client-ui_transcript.pdf
create-netflix-clone-06-client-ui_transcript.pdf
 
create-netflix-clone-03-server.pdf
create-netflix-clone-03-server.pdfcreate-netflix-clone-03-server.pdf
create-netflix-clone-03-server.pdf
 
create-netflix-clone-04-server-continued.pdf
create-netflix-clone-04-server-continued.pdfcreate-netflix-clone-04-server-continued.pdf
create-netflix-clone-04-server-continued.pdf
 
create-netflix-clone-05-client-model_transcript.pdf
create-netflix-clone-05-client-model_transcript.pdfcreate-netflix-clone-05-client-model_transcript.pdf
create-netflix-clone-05-client-model_transcript.pdf
 
create-netflix-clone-03-server_transcript.pdf
create-netflix-clone-03-server_transcript.pdfcreate-netflix-clone-03-server_transcript.pdf
create-netflix-clone-03-server_transcript.pdf
 
create-netflix-clone-02-server.pdf
create-netflix-clone-02-server.pdfcreate-netflix-clone-02-server.pdf
create-netflix-clone-02-server.pdf
 
create-netflix-clone-05-client-model.pdf
create-netflix-clone-05-client-model.pdfcreate-netflix-clone-05-client-model.pdf
create-netflix-clone-05-client-model.pdf
 
Creating a Whatsapp Clone - Part IX - Transcript.pdf
Creating a Whatsapp Clone - Part IX - Transcript.pdfCreating a Whatsapp Clone - Part IX - Transcript.pdf
Creating a Whatsapp Clone - Part IX - Transcript.pdf
 
Creating a Whatsapp Clone - Part V - Transcript.pdf
Creating a Whatsapp Clone - Part V - Transcript.pdfCreating a Whatsapp Clone - Part V - Transcript.pdf
Creating a Whatsapp Clone - Part V - Transcript.pdf
 
Creating a Whatsapp Clone - Part IV - Transcript.pdf
Creating a Whatsapp Clone - Part IV - Transcript.pdfCreating a Whatsapp Clone - Part IV - Transcript.pdf
Creating a Whatsapp Clone - Part IV - Transcript.pdf
 
Creating a Whatsapp Clone - Part IV.pdf
Creating a Whatsapp Clone - Part IV.pdfCreating a Whatsapp Clone - Part IV.pdf
Creating a Whatsapp Clone - Part IV.pdf
 
Creating a Whatsapp Clone - Part I - Transcript.pdf
Creating a Whatsapp Clone - Part I - Transcript.pdfCreating a Whatsapp Clone - Part I - Transcript.pdf
Creating a Whatsapp Clone - Part I - Transcript.pdf
 
Creating a Whatsapp Clone - Part IX.pdf
Creating a Whatsapp Clone - Part IX.pdfCreating a Whatsapp Clone - Part IX.pdf
Creating a Whatsapp Clone - Part IX.pdf
 
Creating a Whatsapp Clone - Part VI.pdf
Creating a Whatsapp Clone - Part VI.pdfCreating a Whatsapp Clone - Part VI.pdf
Creating a Whatsapp Clone - Part VI.pdf
 

Recently uploaded

20240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 202420240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 2024
Matthew Sinclair
 
Microsoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdfMicrosoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdf
Uni Systems S.M.S.A.
 
Data structures and Algorithms in Python.pdf
Data structures and Algorithms in Python.pdfData structures and Algorithms in Python.pdf
Data structures and Algorithms in Python.pdf
TIPNGVN2
 
Building RAG with self-deployed Milvus vector database and Snowpark Container...
Building RAG with self-deployed Milvus vector database and Snowpark Container...Building RAG with self-deployed Milvus vector database and Snowpark Container...
Building RAG with self-deployed Milvus vector database and Snowpark Container...
Zilliz
 
Pushing the limits of ePRTC: 100ns holdover for 100 days
Pushing the limits of ePRTC: 100ns holdover for 100 daysPushing the limits of ePRTC: 100ns holdover for 100 days
Pushing the limits of ePRTC: 100ns holdover for 100 days
Adtran
 
Video Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the FutureVideo Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the Future
Alpen-Adria-Universität
 
20240609 QFM020 Irresponsible AI Reading List May 2024
20240609 QFM020 Irresponsible AI Reading List May 202420240609 QFM020 Irresponsible AI Reading List May 2024
20240609 QFM020 Irresponsible AI Reading List May 2024
Matthew Sinclair
 
20240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 202420240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 2024
Matthew Sinclair
 
How to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For FlutterHow to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For Flutter
Daiki Mogmet Ito
 
UiPath Test Automation using UiPath Test Suite series, part 5
UiPath Test Automation using UiPath Test Suite series, part 5UiPath Test Automation using UiPath Test Suite series, part 5
UiPath Test Automation using UiPath Test Suite series, part 5
DianaGray10
 
How to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptxHow to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptx
danishmna97
 
“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...
“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...
“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...
Edge AI and Vision Alliance
 
RESUME BUILDER APPLICATION Project for students
RESUME BUILDER APPLICATION Project for studentsRESUME BUILDER APPLICATION Project for students
RESUME BUILDER APPLICATION Project for students
KAMESHS29
 
Enchancing adoption of Open Source Libraries. A case study on Albumentations.AI
Enchancing adoption of Open Source Libraries. A case study on Albumentations.AIEnchancing adoption of Open Source Libraries. A case study on Albumentations.AI
Enchancing adoption of Open Source Libraries. A case study on Albumentations.AI
Vladimir Iglovikov, Ph.D.
 
National Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practicesNational Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practices
Quotidiano Piemontese
 
Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !
KatiaHIMEUR1
 
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
James Anderson
 
Introduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - CybersecurityIntroduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - Cybersecurity
mikeeftimakis1
 
Introducing Milvus Lite: Easy-to-Install, Easy-to-Use vector database for you...
Introducing Milvus Lite: Easy-to-Install, Easy-to-Use vector database for you...Introducing Milvus Lite: Easy-to-Install, Easy-to-Use vector database for you...
Introducing Milvus Lite: Easy-to-Install, Easy-to-Use vector database for you...
Zilliz
 
A tale of scale & speed: How the US Navy is enabling software delivery from l...
A tale of scale & speed: How the US Navy is enabling software delivery from l...A tale of scale & speed: How the US Navy is enabling software delivery from l...
A tale of scale & speed: How the US Navy is enabling software delivery from l...
sonjaschweigert1
 

Recently uploaded (20)

20240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 202420240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 2024
 
Microsoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdfMicrosoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdf
 
Data structures and Algorithms in Python.pdf
Data structures and Algorithms in Python.pdfData structures and Algorithms in Python.pdf
Data structures and Algorithms in Python.pdf
 
Building RAG with self-deployed Milvus vector database and Snowpark Container...
Building RAG with self-deployed Milvus vector database and Snowpark Container...Building RAG with self-deployed Milvus vector database and Snowpark Container...
Building RAG with self-deployed Milvus vector database and Snowpark Container...
 
Pushing the limits of ePRTC: 100ns holdover for 100 days
Pushing the limits of ePRTC: 100ns holdover for 100 daysPushing the limits of ePRTC: 100ns holdover for 100 days
Pushing the limits of ePRTC: 100ns holdover for 100 days
 
Video Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the FutureVideo Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the Future
 
20240609 QFM020 Irresponsible AI Reading List May 2024
20240609 QFM020 Irresponsible AI Reading List May 202420240609 QFM020 Irresponsible AI Reading List May 2024
20240609 QFM020 Irresponsible AI Reading List May 2024
 
20240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 202420240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 2024
 
How to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For FlutterHow to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For Flutter
 
UiPath Test Automation using UiPath Test Suite series, part 5
UiPath Test Automation using UiPath Test Suite series, part 5UiPath Test Automation using UiPath Test Suite series, part 5
UiPath Test Automation using UiPath Test Suite series, part 5
 
How to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptxHow to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptx
 
“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...
“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...
“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...
 
RESUME BUILDER APPLICATION Project for students
RESUME BUILDER APPLICATION Project for studentsRESUME BUILDER APPLICATION Project for students
RESUME BUILDER APPLICATION Project for students
 
Enchancing adoption of Open Source Libraries. A case study on Albumentations.AI
Enchancing adoption of Open Source Libraries. A case study on Albumentations.AIEnchancing adoption of Open Source Libraries. A case study on Albumentations.AI
Enchancing adoption of Open Source Libraries. A case study on Albumentations.AI
 
National Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practicesNational Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practices
 
Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !
 
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
 
Introduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - CybersecurityIntroduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - Cybersecurity
 
Introducing Milvus Lite: Easy-to-Install, Easy-to-Use vector database for you...
Introducing Milvus Lite: Easy-to-Install, Easy-to-Use vector database for you...Introducing Milvus Lite: Easy-to-Install, Easy-to-Use vector database for you...
Introducing Milvus Lite: Easy-to-Install, Easy-to-Use vector database for you...
 
A tale of scale & speed: How the US Navy is enabling software delivery from l...
A tale of scale & speed: How the US Navy is enabling software delivery from l...A tale of scale & speed: How the US Navy is enabling software delivery from l...
A tale of scale & speed: How the US Navy is enabling software delivery from l...
 

Creating a Whatsapp Clone - Part XV - Transcript.pdf

  • 1. Creating a WhatsApp Clone - Part XV Next we’ll jump to the websocket package which is the last package
  • 2. @Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { @Bean public ServletServerContainerFactoryBean createWebSocketContainer() { ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean(); container.setMaxTextMessageBufferSize(8192); container.setMaxBinaryMessageBufferSize(8192); return container; } @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(myHandler(), "/socket"); } @Bean public WebSocketHandler myHandler() { AppSocket First we need to configure the web socket. We do this by implementing the WebSocketConfigurer and using the annotations on the class to indicate its purpose
  • 3. @Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { @Bean public ServletServerContainerFactoryBean createWebSocketContainer() { ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean(); container.setMaxTextMessageBufferSize(8192); container.setMaxBinaryMessageBufferSize(8192); return container; } @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(myHandler(), "/socket"); } @Bean public WebSocketHandler myHandler() { AppSocket We define the socket so we can define the packet size to 8kb. We can set a larger size but generally keeping packets small is a good practice
  • 4. public ServletServerContainerFactoryBean createWebSocketContainer() { ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean(); container.setMaxTextMessageBufferSize(8192); container.setMaxBinaryMessageBufferSize(8192); return container; } @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(myHandler(), "/socket"); } @Bean public WebSocketHandler myHandler() { return new AppSocket(); } @Bean public TaskScheduler taskScheduler() { return new ConcurrentTaskScheduler(Executors. newSingleThreadScheduledExecutor()); } AppSocket The AppSocket class is bound to the /socket URL in this line of code
  • 5. container.setMaxTextMessageBufferSize(8192); container.setMaxBinaryMessageBufferSize(8192); return container; } @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(myHandler(), "/socket"); } @Bean public WebSocketHandler myHandler() { return new AppSocket(); } @Bean public TaskScheduler taskScheduler() { return new ConcurrentTaskScheduler(Executors. newSingleThreadScheduledExecutor()); } } AppSocket This is the thread used to process the websocket connections. We can allocate more thread resources based on need
  • 6. import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.handler.TextWebSocketHandler; public class AppSocket extends TextWebSocketHandler { private static Logger log = Logger.getLogger(AppSocket.class.getName()); private static final Map<String, List<WebSocketSession>> clients = new HashMap<>(); @Autowired private UserService users; private static boolean sendToToken(String token, String json) { List<WebSocketSession> ws = clients.get(token); WebSocketSession currentSocket = null; try { if(ws != null) { TextMessage t = new TextMessage(json); List<WebSocketSession> removeQueue = null; for(WebSocketSession w : ws) { currentSocket = w; if(currentSocket.isOpen()) { AppSocket Next lets go to AppSocket The app socket is an implementation of TextWebSocketHandler which handles text messages. Since all our messages are JSON this makes more sense.
  • 7. import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.handler.TextWebSocketHandler; public class AppSocket extends TextWebSocketHandler { private static Logger log = Logger.getLogger(AppSocket.class.getName()); private static final Map<String, List<WebSocketSession>> clients = new HashMap<>(); @Autowired private UserService users; private static boolean sendToToken(String token, String json) { List<WebSocketSession> ws = clients.get(token); WebSocketSession currentSocket = null; try { if(ws != null) { TextMessage t = new TextMessage(json); List<WebSocketSession> removeQueue = null; for(WebSocketSession w : ws) { currentSocket = w; if(currentSocket.isOpen()) { AppSocket I cache the currently active connections here. This isn’t a good approach in the long term. A better approach would be redis for this sort of caching. But for an initial app this can work fine
  • 8. public class AppSocket extends TextWebSocketHandler { private static Logger log = Logger.getLogger(AppSocket.class.getName()); private static final Map<String, List<WebSocketSession>> clients = new HashMap<>(); @Autowired private UserService users; private static boolean sendToToken(String token, String json) { List<WebSocketSession> ws = clients.get(token); WebSocketSession currentSocket = null; try { if(ws != null) { TextMessage t = new TextMessage(json); List<WebSocketSession> removeQueue = null; for(WebSocketSession w : ws) { currentSocket = w; if(currentSocket.isOpen()) { w.sendMessage(t); return true; AppSocket We need access to the UsersService so we can send a message to a group or user.
  • 9. private static final Map<String, List<WebSocketSession>> clients = new HashMap<>(); @Autowired private UserService users; private static boolean sendToToken(String token, String json) { List<WebSocketSession> ws = clients.get(token); WebSocketSession currentSocket = null; try { if(ws != null) { TextMessage t = new TextMessage(json); List<WebSocketSession> removeQueue = null; for(WebSocketSession w : ws) { currentSocket = w; if(currentSocket.isOpen()) { w.sendMessage(t); return true; } else { if(removeQueue == null) { removeQueue = new ArrayList<>(); } removeQueue.add(w); } AppSocket This method sends JSON to a websocket based on the user token and returns true if it succeeded.
  • 10. private static final Map<String, List<WebSocketSession>> clients = new HashMap<>(); @Autowired private UserService users; private static boolean sendToToken(String token, String json) { List<WebSocketSession> ws = clients.get(token); WebSocketSession currentSocket = null; try { if(ws != null) { TextMessage t = new TextMessage(json); List<WebSocketSession> removeQueue = null; for(WebSocketSession w : ws) { currentSocket = w; if(currentSocket.isOpen()) { w.sendMessage(t); return true; } else { if(removeQueue == null) { removeQueue = new ArrayList<>(); } removeQueue.add(w); } AppSocket We get the sessions for the given client
  • 11. private static boolean sendToToken(String token, String json) { List<WebSocketSession> ws = clients.get(token); WebSocketSession currentSocket = null; try { if(ws != null) { TextMessage t = new TextMessage(json); List<WebSocketSession> removeQueue = null; for(WebSocketSession w : ws) { currentSocket = w; if(currentSocket.isOpen()) { w.sendMessage(t); return true; } else { if(removeQueue == null) { removeQueue = new ArrayList<>(); } removeQueue.add(w); } } if(removeQueue != null) { for(WebSocketSession w : removeQueue) { ws.remove(w); } AppSocket If he has a webservice sessions
  • 12. private static boolean sendToToken(String token, String json) { List<WebSocketSession> ws = clients.get(token); WebSocketSession currentSocket = null; try { if(ws != null) { TextMessage t = new TextMessage(json); List<WebSocketSession> removeQueue = null; for(WebSocketSession w : ws) { currentSocket = w; if(currentSocket.isOpen()) { w.sendMessage(t); return true; } else { if(removeQueue == null) { removeQueue = new ArrayList<>(); } removeQueue.add(w); } } if(removeQueue != null) { for(WebSocketSession w : removeQueue) { ws.remove(w); } AppSocket We create a text message with the JSON
  • 13. List<WebSocketSession> ws = clients.get(token); WebSocketSession currentSocket = null; try { if(ws != null) { TextMessage t = new TextMessage(json); List<WebSocketSession> removeQueue = null; for(WebSocketSession w : ws) { currentSocket = w; if(currentSocket.isOpen()) { w.sendMessage(t); return true; } else { if(removeQueue == null) { removeQueue = new ArrayList<>(); } removeQueue.add(w); } } if(removeQueue != null) { for(WebSocketSession w : removeQueue) { ws.remove(w); } } } else { AppSocket We loop over all the websocket connections one by one
  • 14. List<WebSocketSession> ws = clients.get(token); WebSocketSession currentSocket = null; try { if(ws != null) { TextMessage t = new TextMessage(json); List<WebSocketSession> removeQueue = null; for(WebSocketSession w : ws) { currentSocket = w; if(currentSocket.isOpen()) { w.sendMessage(t); return true; } else { if(removeQueue == null) { removeQueue = new ArrayList<>(); } removeQueue.add(w); } } if(removeQueue != null) { for(WebSocketSession w : removeQueue) { ws.remove(w); } } } else { AppSocket If a connection is open we send the message there and return
  • 15. List<WebSocketSession> ws = clients.get(token); WebSocketSession currentSocket = null; try { if(ws != null) { TextMessage t = new TextMessage(json); List<WebSocketSession> removeQueue = null; for(WebSocketSession w : ws) { currentSocket = w; if(currentSocket.isOpen()) { w.sendMessage(t); return true; } else { if(removeQueue == null) { removeQueue = new ArrayList<>(); } removeQueue.add(w); } } if(removeQueue != null) { for(WebSocketSession w : removeQueue) { ws.remove(w); } } } else { AppSocket Otherwise we add the socket to the remove queue. We don’t want to remove in the middle of the loop to prevent an exception.
  • 16. if(removeQueue == null) { removeQueue = new ArrayList<>(); } removeQueue.add(w); } } if(removeQueue != null) { for(WebSocketSession w : removeQueue) { ws.remove(w); } } } else { log.warning("No WS connections for token: " + token); } } catch(IOException err) { log.log(Level.SEVERE, "Exception during sending message", err); if(currentSocket != null && ws != null) { ws.remove(currentSocket); if(ws.isEmpty()) { clients.remove(token); } } } return false; AppSocket We remove all the defunct websockets from the queue in this line
  • 17. removeQueue.add(w); } } if(removeQueue != null) { for(WebSocketSession w : removeQueue) { ws.remove(w); } } } else { log.warning("No WS connections for token: " + token); } } catch(IOException err) { log.log(Level.SEVERE, "Exception during sending message", err); if(currentSocket != null && ws != null) { ws.remove(currentSocket); if(ws.isEmpty()) { clients.remove(token); } } } return false; } public static void sendUserTyping(String token, String id, AppSocket For all the cases where sending via the socket didn't work we return false
  • 18. "","authorId":"" + id + ""}"); } public static boolean sendMessage(String token, String json) { return sendToToken(token, json); } @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { JsonParser parser = JsonParserFactory.getJsonParser(); Map<String, Object> m = parser.parseMap(message.getPayload()); String type = (String)m.get("t"); if(type != null) { if(type.equals("init")) { String token = (String)m.get("tok"); Number time = (Number)m.get("time"); List<WebSocketSession> l = clients.get(token); if(l == null) { l = new ArrayList<>(); clients.put(token, l); } l.add(session); return; AppSocket This method handles the incoming text packets
  • 19. public static boolean sendMessage(String token, String json) { return sendToToken(token, json); } @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { JsonParser parser = JsonParserFactory.getJsonParser(); Map<String, Object> m = parser.parseMap(message.getPayload()); String type = (String)m.get("t"); if(type != null) { if(type.equals("init")) { String token = (String)m.get("tok"); Number time = (Number)m.get("time"); List<WebSocketSession> l = clients.get(token); if(l == null) { l = new ArrayList<>(); clients.put(token, l); } l.add(session); return; } } else { String typing = (String)m.get("typing"); AppSocket First we need to parse the JSON into a map
  • 20. @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { JsonParser parser = JsonParserFactory.getJsonParser(); Map<String, Object> m = parser.parseMap(message.getPayload()); String type = (String)m.get("t"); if(type != null) { if(type.equals("init")) { String token = (String)m.get("tok"); Number time = (Number)m.get("time"); List<WebSocketSession> l = clients.get(token); if(l == null) { l = new ArrayList<>(); clients.put(token, l); } l.add(session); return; } } else { String typing = (String)m.get("typing"); String sentTo = (String)m.get("sentTo"); if(typing != null) { String authorId = (String)m.get("authorId"); users.userTyping(authorId, sentTo, true); AppSocket If a message has a type it’s probably an init message
  • 21. @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { JsonParser parser = JsonParserFactory.getJsonParser(); Map<String, Object> m = parser.parseMap(message.getPayload()); String type = (String)m.get("t"); if(type != null) { if(type.equals("init")) { String token = (String)m.get("tok"); Number time = (Number)m.get("time"); List<WebSocketSession> l = clients.get(token); if(l == null) { l = new ArrayList<>(); clients.put(token, l); } l.add(session); return; } } else { String typing = (String)m.get("typing"); String sentTo = (String)m.get("sentTo"); if(typing != null) { String authorId = (String)m.get("authorId"); users.userTyping(authorId, sentTo, true); AppSocket init messages allow us to add a websocket to our cache of connections so we can push a message back into the websocket when we need to send a server notification
  • 22. l = new ArrayList<>(); clients.put(token, l); } l.add(session); return; } } else { String typing = (String)m.get("typing"); String sentTo = (String)m.get("sentTo"); if(typing != null) { String authorId = (String)m.get("authorId"); users.userTyping(authorId, sentTo, true); } else { String id = (String)m.get("id"); if(id == null) { users.sendMessage(sentTo, m); } else { users.sendJSONTo(sentTo, message.getPayload()); } } } } AppSocket Otherwise we test if this is a “user typing" event in which case we send a typing message onward
  • 23. l = new ArrayList<>(); clients.put(token, l); } l.add(session); return; } } else { String typing = (String)m.get("typing"); String sentTo = (String)m.get("sentTo"); if(typing != null) { String authorId = (String)m.get("authorId"); users.userTyping(authorId, sentTo, true); } else { String id = (String)m.get("id"); if(id == null) { users.sendMessage(sentTo, m); } else { users.sendJSONTo(sentTo, message.getPayload()); } } } } AppSocket Finally we send the message as JSON to the users in the group or the specific user. This invokes the code we saw in the user service class
  • 24. @Override public void handleTransportError(WebSocketSession wss, Throwable thrwbl) throws Exception { log.log(Level.SEVERE, "Error during transport", thrwbl); } @Override public void afterConnectionClosed(WebSocketSession wss, CloseStatus cs) throws Exception { for(String s : clients.keySet()) { List<WebSocketSession> wl = clients.get(s); for(WebSocketSession w : wl) { if(w == wss) { wl.remove(w); if(wl.isEmpty()) { clients.remove(s); } return; } } } } AppSocket When a connection is closed we loop over the existing list and purge it of the dead connection
  • 25. @Override public void afterConnectionClosed(WebSocketSession wss, CloseStatus cs) throws Exception { for(String s : clients.keySet()) { List<WebSocketSession> wl = clients.get(s); for(WebSocketSession w : wl) { if(w == wss) { wl.remove(w); if(wl.isEmpty()) { clients.remove(s); } return; } } } } @Override public boolean supportsPartialMessages() { return false; } } AppSocket For simplicity we don't support partial messages which shouldn’t be necessary for small 8kb messages. With that the class is done