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?
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
Lets do some real life example with Java
Steps:
- Create a Dynamic Web Project. In Eclipse Go File>New>Other and choose “Dynamic Web Project” under Web.
- Add files shown in the following image. Content of each of the file will be discussed later.
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.
You can open multiple browser window to see the effect when task status(close/open) is changed or task is removed.
Add a Comment