Thursday, March 15, 2018

Javascript WebSocket Client Example

In javascript WebSocket API below are the methods that you may need to implement when communicating with a server.
  websocket.onopen - This method gets executed when a connection between the client and the server is created.
  websocket.onclose - This method gets executed when a connection is closed.
  websocket.onmessage This method gets executed when a message is received from server.
  websocket.onerror - This will be called if an unhandled error is thrown in above methods.

Below HTML page contains a sample code.

<!DOCTYPE HTML>
<html>
   <head>
      <script type="text/javascript">
         var ws;
         function loadWebsocket() {
            if (window.WebSocket) {
               //The browser supports WebSockets");
               // Open a web socket
               ws = new WebSocket("ws://localhost:8080/WebsocketServer1/chat");
               ws.onopen = function() {
                  console.log("Connection is opened...");
               };

               ws.onmessage = function (evt) { 
                  var message = evt.data;
                  console.log("Message is received...:" + message);
               };

               ws.onclose = function() { 
                  console.log("Connection is closed..."); 
               };

ws.onerror = function() {
console.log("Error occured...");
};
               
               window.onbeforeunload = function(event) {
                  socket.close();
               };
            } else {
               // The browser doesn't support WebSocket
               console.log("Your browser doesn't support WebSockets!");
            }
         }
 
         function sendMessage() {
          ws.send("Hello server!");
        }
        
         loadWebsocket();
      </script>

   </head>
   <body>
   
      <div id="sse">
         <a href="javascript:sendMessage()">Send message</a>
      </div>
      
   </body>
</html>
  
  

Tuesday, March 13, 2018

Java Websocket Example With Simple Server and Client

In usual websites, how the communication between the client(Browser) and the server happen is first the client(browser) sends a request to the server and the server responses to the client. Apart from this usual behavior, there can be situations where a server needs to send data to a client at an arbitrary time. A chat server is such an example.

The process of creation of a WebSocket connection between a a server and a client is as below.
First the client sends an HTTP request to the server with "Connection: Upgrade" and "Upgrade: websocket" headers. Once the server sees above headers it knows that the client wants to make a WebSocket connection.
Then the server sends a response to the client by including above two header parameters.
Websocket communication is done using TCP/IP protocol. So then the current HTTP connection is upgraded to a TCP/IP connection.

In below example, I will show you how to write a simple websocket client and a server. In order to keep this example clearer I purposely avoided introducing best practices and patterns to the code.

1.Server
Create a new maven project. Set the artifact name as WebsocketServer1 and packaging as war. Open the pom.xml and add below configs.
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
</dependency>
</dependencies>

Now we are going to create the class which acts as the server endpoint. Create a new class and name it as MyServerEndpoint. The content of the class will be as below.

import java.io.IOException;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint("/chat")
public class MyServerEndpoint {

  public MyServerEndpoint() {
      System.out.println("MyServerEndpoint created......");
  }

  @OnOpen
  public void onOpen(Session session) {
      System.out.printf("Connection opened....");
      try {
          session.getBasicRemote().sendText("Your connection accepted...");
      } catch (IOException ex) {
          ex.printStackTrace();
      }
  }
  
  @OnClose
  public void onClose(Session session) {
  System.out.printf("Connection closed....");
  }
  
  @OnError
  public void onError(Throwable e) {
  System.out.printf("Error occurred....");
  e.printStackTrace();
  }

  @OnMessage
  public void onMessage(String message, Session session) {
      System.out.printf("Message from client: " + message);
      try {
          session.getBasicRemote().sendText(String.format("Hi client, we got your message '" + message + "'"));
      } catch (IOException ex) {
          ex.printStackTrace();
      }
  }
}

Now you can run this web application in tomcat server. Then this endpoint will be deployed and will be listening on below endpoint.
ws://localhost:8080/WebsocketServer1/chat

2.Client
Now I am going to create a websocket client which can communicate with the above server.
Create a new maven project. Set the artifact name as WebsocketClient1 and the packaging as jar.
Add below dependencies to your pom.xml.
Note that javax.websocket-api contains the interfaces for websocket API.  Tyrus is an implementation of above API. Tomcat-websocket and jetty-websocket are another such implementations.

<dependency>
<groupId>javax.websocket</groupId>
<artifactId>javax.websocket-api</artifactId>
<version>1.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.glassfish.tyrus</groupId>
<artifactId>tyrus-client</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.tyrus</groupId>
<artifactId>tyrus-container-grizzly</artifactId>
<version>1.1</version>
</dependency>

Create a new java class as below. This is your websocket client.

import java.net.URI;
import javax.websocket.ClientEndpoint;
import javax.websocket.CloseReason;
import javax.websocket.ContainerProvider;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.WebSocketContainer;

@ClientEndpoint
public class MyClient {
    Session userSession = null;
    public static void main(String[] args) {
new MyClient().execute();
    }

    public void execute() {
try {
         URI endpointURI = (new URI("ws://localhost:8080/WebsocketServer1/chat"));
    WebSocketContainer container = ContainerProvider.getWebSocketContainer();
    Session session = container.connectToServer(this, endpointURI);

    sendMessage("Hello Server!");
    session.close();
} catch (Exception ex) {
    ex.printStackTrace();
}
    }

    @OnOpen
    public void onOpen(Session userSession) {
        this.userSession = userSession;
        System.out.println("Websocket connection opened.");
    }

    @OnClose
    public void onClose(Session userSession, CloseReason reason) {
        this.userSession = null;
        System.out.println("Websocket connection closed.");
    }

    @OnMessage
    public void onMessage(String message) {
        System.out.println("From server: " + message);
    }
    
    public void sendMessage(String message) {
        this.userSession.getAsyncRemote().sendText(message);
    }
}

Now we are ready to test our server and client. First run the server project on tomcat. Then run the client class. You will see below output in server console.
MyServerEndpoint created......
Connection opened....
Message from client: Hello Server!
Connection closed....

And you will see below output in clients console.
Websocket connection opened.
From server: Your connection accepted...
From server: Hi client, we got your message 'Hello Server!'
Websocket connection closed.

Below are the annotations used.
  @ServerEndpoint - Defines this as a server endpoint which is bound to the path given within brackets
  @OnOpen - This method gets executed when a connection between the client and the server is created
  @OnClose - This method gets executed when a connection is closed
  @OnError - This will be called if an unhandled excetion thrown in other annotated methods.
  @OnMessage This method gets executed when a message is received from other party
  @ClientEndpoint - Defines this as a websocket client. In order to the other annotation to work this annotation should be there.

Security:
DO not use unsecured websocket connections(ws://) in pages loaded in HTTPS. Instead, use secured (wss://) connections.