WebSocket Programming

WebSocket Programming

What Is WebSocket?

  • WebSocket is an advanced technology that makes it possible to open an interactive communication session between the user’s browser and a server. With this API, you can send messages to a server and receive event-driven responses without having to poll the server for a reply. 
  • WebSocket is a different TCP protocol from HTTP.
  • Both protocols are located at layer 7 in the OSI model and, as such, depend on TCP at layer 4.

This blog post will cover WebSocket programming. To learn more about Socket programming, check out our Socket programming blog post!

How WebSocket Works?

Diagram showing how WebSocket programming works.

When WebSocket Used?

  • Real-time applications
  • Chat apps
  • IoT (Internet of Things)
  • Online multiplayer games

Learn more about WebSockets and how they work from this blog post!

When we should avoid using WebSockets?

Don’t think you will need a real-time app if you are building a simple CMS, unless you want some kind of a specific real-time feature. For a RESTful-API I would advise not using Web Sockets as HTTP GET, POST, DELETE, PUT and many other requests are awesome for that.

Browser Supports

Screenshot showing the WebSocket browser support.

Lets do some real life example with Java

Steps:

  1. Create a Dynamic Web Project. In Eclipse Go File>New>Other and choose “Dynamic Web Project” under Web.
  2. Add files shown in the following image. Content of each of the file will be discussed later.
Screenshot of the WebSocket Project Structure.

Task.java

1 package com.ixora.model;
2 3 public class Task {
4    private int id;
5    private String name;
6    private String status;
7 8 9    public Task() {
10    }
11 12    public int getId() {
13 return id;
14    }
15 16    public String getName() {
17 return name;
18    }
19 20    public String getStatus() {
21 return status;
22    }
23 24    public void setId(int id) {
25 this.id = id;
26    }
27 28    public void setName(String name) {
29 this.name = name;
30    }
31 32    public void setStatus(String status) {
33 this.status = status;
34    }
35 36 }Code language: JavaScript (javascript)

TaskSessionHandler.java

1 package com.ixora.websocket;
2 3 import java.io.IOException;
4 import java.util.ArrayList;
5 import java.util.HashSet;
6 import java.util.List;
7 import java.util.Set;
8 import java.util.logging.Level;
9 import java.util.logging.Logger;
10 11 import javax.enterprise.context.ApplicationScoped;
12 import javax.json.JsonObject;
13 import javax.json.spi.JsonProvider;
14 import javax.websocket.Session;
15 16 import com.ixora.model.Task;
17 18 @ApplicationScoped
19 public class TaskSessionHandler {
20    private int taskId = 0;
21    private final Set<Session> sessions = new HashSet<>();
22    private final Set<Task> tasks = new HashSet<>();
23 24    public void addSession(Session session) {
25        sessions.add(session);
26 for (Task task : tasks) {
27            JsonObject addMessage = createAddMessage(task);
28            sendToSession(session, addMessage);
29        }
30    }
31 32    public void removeSession(Session session) {
33        sessions.remove(session);
34    }
35 36    public List<Task> getTasks() {
37 return new ArrayList<>(tasks);
38    }
39 40    public void addTask(Task task) {
41 42        task.setId(taskId);
43        tasks.add(task);
45        taskId++;
46        JsonObject addMessage = createAddMessage(task);
47        sendToAllConnectedSessions(addMessage);
48    }
49 50    public void removeTask(int id) {
51        Task task = getTaskById(id);
52 if (task != null) {
53            tasks.remove(task);
54            JsonProvider provider = JsonProvider.provider();
55            JsonObject removeMessage = provider.createObjectBuilder().add("action", "remove").add("id", id).build();
56            sendToAllConnectedSessions(removeMessage);
57        }
58    }
59 60    public void toggleDevice(int id) {
61        JsonProvider provider = JsonProvider.provider();
62        Task task = getTaskById(id);
63 if (task != null) {
64 if ("Open".equals(task.getStatus())) {
65                task.setStatus("Close");
66            } else {
67                task.setStatus("Open");
68            }
69            JsonObject updateDevMessage = provider.createObjectBuilder().add("action", "toggle")
70                    .add("id", task.getId()).add("status", task.getStatus()).build();
71            sendToAllConnectedSessions(updateDevMessage);
72        }
73    }
74 75    private Task getTaskById(int id) {
76 for (Task task : tasks) {
77 if (task.getId() == id) {
78 return task;
79            }
80        }
81 return null;
82    }
83 84    private JsonObject createAddMessage(Task task) {
85        JsonProvider provider = JsonProvider.provider();
86        JsonObject addMessage = provider.createObjectBuilder().add("action", "add").add("id", task.getId())
87                .add("name", task.getName()).add("status", task.getStatus()).build();
88 return addMessage;
89    }
90 91    private void sendToAllConnectedSessions(JsonObject message) {
92 for (Session session : sessions) {
93            sendToSession(session, message);
94        }
95    }
96 97    private void sendToSession(Session session, JsonObject message) {
98 try {
99            session.getBasicRemote().sendText(message.toString());
100        } catch (IOException ex) {
101            sessions.remove(session);
102            Logger.getLogger(TaskSessionHandler.class.getName()).log(Level.SEVERE, null, ex);
103        }
104    }
105 }Code language: JavaScript (javascript)

TaskWebSocketServer.java

1 package com.ixora.websocket;
2 3 import java.io.StringReader;
4 import java.util.logging.Level;
5import java.util.logging.Logger;
6 7 import javax.enterprise.context.ApplicationScoped;
8 import javax.inject.Inject;
9 import javax.json.Json;
10 import javax.json.JsonObject;
11 import javax.json.JsonReader;
12 import javax.websocket.OnClose;
13 import javax.websocket.OnError;
14 import javax.websocket.OnMessage;
15 import javax.websocket.OnOpen;
16 import javax.websocket.Session;
17 import javax.websocket.server.ServerEndpoint;
18 19 import com.ixora.model.Task;
20 21 @ApplicationScoped
22 @ServerEndpoint("/actions")
23 public class TaskWebSocketServer {
24 25    @Inject
26    private TaskSessionHandler sessionHandler;
27 28    @OnOpen
29    public void open(Session session) {
30        sessionHandler.addSession(session);
31    }
32 33    @OnClose
34    public void close(Session session) {
35        sessionHandler.removeSession(session);
36    }
37 38    @OnError
39    public void onError(Throwable error) {
40        Logger.getLogger(TaskWebSocketServer.class.getName()).log(Level.SEVERE, null, error);
41    }
42 43    @OnMessage
44    public void handleMessage(String message, Session session) {
45 try (JsonReader reader = Json.createReader(new StringReader(message))) {
46            JsonObject jsonMessage = reader.readObject();
47 48 if ("add".equals(jsonMessage.getString("action"))) {
49                Task task = new Task();
50                task.setName(jsonMessage.getString("name"));                
51                task.setStatus("Open");
52                sessionHandler.addTask(task);
53            }
54 55 if ("remove".equals(jsonMessage.getString("action"))) {
56                int id = (int) jsonMessage.getInt("id");
57                sessionHandler.removeTask(id);
58            }
59 60 if ("toggle".equals(jsonMessage.getString("action"))) {
61                int id = (int) jsonMessage.getInt("id");
62                sessionHandler.toggleDevice(id);
63            }
64        }
65    }
66 }Code language: JavaScript (javascript)

index.html

1 <!DOCTYPE html>
2 <html>
3    <head>
4        <title></title>
5        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
6        <script src="/websocket.js"></script>
7        <link rel="stylesheet" type="text/css" href="/style.css">
8    </head>
9    <body>
10 
11        <div id="wrapper">
12            <h1>Java Websocket</h1>
13            <p>Click the Add a task button to start adding Tasks.</p>
15            <br />
16            <div id="addTask">
17                <div class="button"> <a href="#" OnClick="showForm()">Add a task</a> </div>
18                <form id="addTaskForm">
19                    <h3>Add a new task</h3>
20                    <span>Name: <input type="text" name="task_name" id="task_name"></span>
21                    <input type="button" class="button" value="Add" onclick=formSubmit()>
22                    <input type="reset" class="button" value="Cancel" onclick=hideForm()>
23                </form>
24            </div>
25            <br />
26            <h3>Currently showing tasks:</h3>
27            <div id="content">
28            </div>
29        </div>
30    </body>
31 </html>Code language: HTML, XML (xml)

style.css

1 body {
2    font-family: Arial, Helvetica, sans-serif;
3    font-size: 80%;
4    background-color: #1f1f1f; 5 }
6 7 #wrapper { 8    width: 960px;
9    margin: auto;
10    text-align: left;
11    color: #d9d9d9; 12 }
13 14 p {
15    text-align: left;
16 }
17 18 .button {
19    display: inline;
20    color: #fff; 21    background-color: #f2791d; 22    padding: 8px;
23    margin: auto;
24    border-radius: 8px;
25    -moz-border-radius: 8px;
26    -webkit-border-radius: 8px;
27    box-shadow: none;
28    border: none;
29 }
30 31 .button:hover {
32    background-color: #ffb15e; 33 }
34 .button a, a:visited, a:hover, a:active {
35    color: #fff; 36    text-decoration: none;
37 }
38 39 #addTask { 40    text-align: center;
41    width: 960px;
42    margin: auto;
43    margin-bottom: 10px;
44 }
45 46 #addTaskForm { 47    text-align: left;
48    width: 400px;
49    margin: auto;
50    padding: 10px;
51 }
52 53 #addTaskForm span { 54    display: block;
55 }
56 57 #content { 58    margin: auto;
59    width: 960px;
60 }
61 62 .task {
63    padding-right: 10px;
64    display: inline-block;
65 }
66 67 .task.open {
68    text-decoration: none;
69 }
70 71 .task.close {    
72    text-decoration: line-through;
73 }
74 75 .task span {
78    display: block;
79 }
80 81 .taskName {
82    text-align: center;
83    font-weight: bold;
84    margin-bottom: 12px;
85 }
89 90 .removeTask {
91    margin-top: 12px;
92    text-align: center;
93 }
94 95 .task a {
96    text-decoration: none;
97 }
98 99 .task a:visited, a:active, a:hover {
100    color: #fff; 102 }
103 104 .task a:hover {
105    text-decoration: underline;
106 }Code language: PHP (php)

websocket.js

1 window.onload = init;
2 var socket = new WebSocket("ws://localhost:8080/WebSocket/actions");
3 socket.onmessage = onMessage;
 
function onMessage(event) {
4 5 var task = JSON.parse(event.data);
6 if (task.action === "add") {
7        printTaskElement(task);
8    }
9 if (task.action === "remove") {
10 document.getElementById(task.id).remove();
11    }
12 if (task.action === "toggle") {
13 var node = document.getElementById(task.id);
14 var nameText = node.children[0];
15 var statusText = node.children[1];
16 if (task.status === "Open") {
17            nameText.setAttribute("class", "task open");
18            statusText.innerHTML = "(<a href=\"#\" OnClick=toggleTask(" + task.id
19            + ")>Close</a>)";
20        } else if (task.status === "Close") {
21            nameText.setAttribute("class", "task close");
22            statusText.innerHTML = " (<a href=\"#\" OnClick=toggleTask(" + task.id
23            + ")>Open</a>)";
24        }   
25 26    }
27 }
28 29 function addTask(name) {
30 var taskAction = {
31        action : "add",
32        name : name
33    };
34    socket.send(JSON.stringify(taskAction));
35 }
36 37 function removeTask(element) {
38 var id = element;
39 var taskAction = {
40        action : "remove",
41        id : id
42    };
43    socket.send(JSON.stringify(taskAction));
44 }
45 46 function toggleTask(element) {
47 var id = element;
48 var taskAction = {
49        action : "toggle",
50        id : id
51    };
52    socket.send(JSON.stringify(taskAction));
53 }
54 55 function printTaskElement(task) {
56 var content = document.getElementById("content");
57 58 var taskDiv = document.createElement("div");
59    taskDiv.setAttribute("id", task.id);
60    content.appendChild(taskDiv);
61 62 var taskName = document.createElement("span");  
63    taskName.innerHTML = task.name; 
63 64 var taskStatus = document.createElement("span");
65 if (task.status === "Open") {
66        taskName.setAttribute("class", "task open");
67        taskStatus.innerHTML = "(<a href=\"#\" OnClick=toggleTask(" + task.id
68                + ")>Close</a>)";
69    } else if (task.status === "Close") {
70        taskName.setAttribute("class", "task close");
71        taskStatus.innerHTML = " (<a href=\"#\" OnClick=toggleTask(" + task.id
72                + ")>Open</a>)";
73    }
74 75    taskDiv.appendChild(taskName);
76    taskDiv.appendChild(taskStatus);
77 78 var removeTask = document.createElement("span");
79    removeTask.setAttribute("class", "removeTask");
80    removeTask.innerHTML = "<a href=\"#\" OnClick=removeTask(" + task.id
81            + ")>Remove task</a>";
82    taskDiv.appendChild(removeTask);
83 }
84 85 function showForm() {
86 document.getElementById("addTaskForm").style.display = '';
87 }
88 89 function hideForm() {
90 document.getElementById("addTaskForm").style.display = "none";
91 }
92 93 function formSubmit() {
94 var form = document.getElementById("addTaskForm");
95 var name = form.elements["task_name"].value;
96    hideForm();
97 document.getElementById("addTaskForm").reset();
98    addTask(name);
99 }
100 101 function init() {
102    hideForm();
103 }Code language: JavaScript (javascript)

I have used Glass Fish Server to run this application. After running the application into the server the out put will be as below.

Screenshot of Running sample WebSocket application using Glass Fish Server.

You can open multiple browser window to see the effect when task status(close/open) is changed or task is removed.

Add a Comment

Your email address will not be published. Required fields are marked *