Skip to content

Instantly share code, notes, and snippets.

@teocci
Last active March 16, 2020 08:54
Show Gist options
  • Save teocci/8de7012f6f9774a3e7054568294afbec to your computer and use it in GitHub Desktop.
Save teocci/8de7012f6f9774a3e7054568294afbec to your computer and use it in GitHub Desktop.
## Client side
Now we need to write the client-side of our `websocket` test application:
page.html
<!DOCTYPE html>
<html>
<head>
<title>Testing websockets</title>
<script src="websocket.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div>
<input id="inputmessage" type="text" />
</div>
<div>
<input type="submit" value="Broadcast message" onclick="send()" />
</div>
<div id="messages"></div>
</body>
</html>
var webSocket =
new WebSocket('ws://localhost:8080/project_name/websocket');
webSocket.onerror = function(event) {
onError(event)
};
webSocket.onopen = function(event) {
onOpen(event)
};
webSocket.onmessage = function(event) {
onMessage(event)
};
function onMessage(event) {
document.getElementById('messages').innerHTML
+= '<br />Received message: ' + event.data;
}
function onOpen(event) {
document.getElementById('messages').innerHTML
= 'Connection established';
}
function onError(event) {
alert(event.data);
}
function send() {
var txt = document.getElementById('inputmessage').value;
webSocket.send(txt);
return false;
}
package com.byteslounge.websockets;
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
@ServerEndpoint("/websocket")
public class WebSocketServer {
private static Set<Session> clients =
Collections.synchronizedSet(new HashSet<Session>());
@OnMessage
public void onMessage(String message, Session session)
throws IOException {
synchronized(clients){
// Iterate over the connected sessions
// and broadcast the received message
for(Session client : clients){
if (!client.equals(session)){
client.getBasicRemote().sendText(message);
}
}
}
}
@OnOpen
public void onOpen (Session session) {
// Add session to the connected sessions set
clients.add(session);
}
@OnClose
public void onClose (Session session) {
// Remove session from the connected sessions set
clients.remove(session);
}
}

WebSockets with multiple clients

In this tutorial we will implement a message broadcast sample application using only HTML5 websockets. The server-side will be implemented with Java EE ServerEndpoint.

Introduction

In this tutorial we will implement an application where clients will interactively send messages to each other through the server. This way we will have an application where clients are in fact publishing and receiving events to/from the server over HTML5 websockets.

This tutorial considers the following environment:

  • Ubuntu 12.04
  • JDK 1.7.0.21 Note: WebSockets support was introduced in Java EE 7
  • Glassfish 4.0

WebSocket server endpoint

Let's define a JAVA websocket server endpoint:

package com.byteslounge.websockets;

import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint("/websocket")
public class WebSocketTest {

  private static Set<Session> clients = 
    Collections.synchronizedSet(new HashSet<Session>());
  
  @OnMessage
  public void onMessage(String message, Session session) 
    throws IOException {
    
    synchronized(clients){
      // Iterate over the connected sessions
      // and broadcast the received message
      for(Session client : clients){
        if (!client.equals(session)){
          client.getBasicRemote().sendText(message);
        }
      }
    }
    
  }
  
  @OnOpen
  public void onOpen (Session session) {
  // Add session to the connected sessions set
    clients.add(session);
  }

  @OnClose
  public void onClose (Session session) {
    // Remove session from the connected sessions set
    clients.remove(session);
  }
}

Here, we are defining a ServerEndpoint that will be the server endpoint listening from client websocket connections.

We have a static Map that will hold all connected client sessions. This way we may broadcast received messages to other clients (method onMessage). Note that when we receive a message we broadcast it to all connected clients except the one who originated the message in the first place.

Methods onOpen and onClose are called when a client connects or disconnects from the server endpoint respectively. So we add or remove them from the sessions Map accordingly.

When the parameter of type Session is included in the annotated ServerEndpoint methods the container will inject the session that corresponds to the client which originated the event.

Client side

Now we need to write the client-side of our websocket test application:

<!DOCTYPE html>
<html>
  <head>
    <title>Testing websockets</title>
    <script src="websocket.js"></script>
    <link rel="stylesheet" type="text/css" href="style.css">
  </head>
  <body>
    <div>
      <input id="inputmessage" type="text" />
    </div>
    <div>
      <input type="submit" value="Broadcast message" onclick="send()" />
    </div>
    <div id="messages"></div>
  </body>
</html>

This page contains a simple input text where a user may write a message and a button to publish the message to the server over the established websocket channel.

Every time we receive a message from the server we write it into the page.

Combining all together

We may now test our application by accessing the index page from two distinct web browser instances:

http://localhost:8080/project_name/page.html

We will see the Connection established message as expected:

http://localhost:8080/byteslounge/page.html - browser 1
Websocket - Established connection

http://localhost:8080/byteslounge/page.html - browser 2
Websocket - Established connection 2nd browser

Now we write a simple message (ex: "hello") in one of the clients and click the "Broadcast message" button:

The other connected client will receive the published message. Note that the message will be published to every connected client except the one who published the message in the first place (as we defined in the server endpoint):

Conclusion

We have developed a sample application where clients use websockets in full extent to communicate with a Java EE application server, ie. publishing and receiving events.

In our case the received events are sent by other clients. One can easily use a similar approach to enable periodic message sending from server to clients in order to notify them of some arbitrary event occurrence. Downloadable sample

The test was executed in Glassfish 4 (you will need a Java EE 7 compliant application server). The source code is available in this Gists, feel free to Fork it.

@teocci
Copy link
Author

teocci commented Jul 16, 2016

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment