SlideShare a Scribd company logo
1 of 25
Download to read offline
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 WindowsPhoneMohammad 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 todaygerbille
 
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 WebSocketsYakov Fain
 
Qt & Webkit
Qt & WebkitQt & Webkit
Qt & WebkitQT-day
 
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
 
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 .NETBrandon 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 paginateKaty 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 productIgor Lozynskyi
 
Websockets talk at Rubyconf Uruguay 2010
Websockets talk at Rubyconf Uruguay 2010Websockets talk at Rubyconf Uruguay 2010
Websockets talk at Rubyconf Uruguay 2010Ismael Celis
 
Building interactivity with websockets
Building interactivity with websocketsBuilding interactivity with websockets
Building interactivity with websocketsWim Godden
 
Wonderful csom sps barcelona
Wonderful csom sps barcelonaWonderful csom sps barcelona
Wonderful csom sps barcelonaSonja Madsen
 
Correcting Common .NET Async/Await Mistakes
Correcting Common .NET Async/Await MistakesCorrecting Common .NET Async/Await Mistakes
Correcting Common .NET Async/Await MistakesBrandon 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 7Roberto Cortez
 
Unity and WebSockets
Unity and WebSocketsUnity and WebSockets
Unity and WebSocketsJosh Glover
 
Modern Android app library stack
Modern Android app library stackModern Android app library stack
Modern Android app library stackTomáš Kypta
 
Taming Core Data by Arek Holko, Macoscope
Taming Core Data by Arek Holko, MacoscopeTaming Core Data by Arek Holko, Macoscope
Taming Core Data by Arek Holko, MacoscopeMacoscope
 

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
 
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
 
Taming Core Data by Arek Holko, Macoscope
Taming Core Data by Arek Holko, MacoscopeTaming Core Data by Arek Holko, Macoscope
Taming Core Data by Arek Holko, Macoscope
 

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.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 
create-netflix-clone-01-introduction.pdf
create-netflix-clone-01-introduction.pdfcreate-netflix-clone-01-introduction.pdf
create-netflix-clone-01-introduction.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 
create-netflix-clone-03-server.pdf
create-netflix-clone-03-server.pdfcreate-netflix-clone-03-server.pdf
create-netflix-clone-03-server.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 
create-netflix-clone-02-server.pdf
create-netflix-clone-02-server.pdfcreate-netflix-clone-02-server.pdf
create-netflix-clone-02-server.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 

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

Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptxMaking_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptxnull - The Open Security Community
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksSoftradix Technologies
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Wonjun Hwang
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Neo4j
 
Bluetooth Controlled Car with Arduino.pdf
Bluetooth Controlled Car with Arduino.pdfBluetooth Controlled Car with Arduino.pdf
Bluetooth Controlled Car with Arduino.pdfngoud9212
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersThousandEyes
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 

Recently uploaded (20)

Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptxMaking_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptxE-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other Frameworks
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024
 
Hot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort Service
Hot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort ServiceHot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort Service
Hot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort Service
 
Bluetooth Controlled Car with Arduino.pdf
Bluetooth Controlled Car with Arduino.pdfBluetooth Controlled Car with Arduino.pdf
Bluetooth Controlled Car with Arduino.pdf
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 

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