WebSockets tutorial on Wildfly 8

WebSockets are a new way for Web clients to communicate with servers and vice versa, without the overhead of an HTTP protocol. Using a WebSocket connection, Web applications can perform real-time communication instead of having to poll for changes back and forth.

WebSockets feature a full duplex bi-directional communication between the server and the client which will produce a faster, more scalable and more robust high performance real time applications on the web.

How to create your first WebSocket application ? Basically the WebSocket API is available as JavaScript API which communicates with the server. On the Server side, the Expert Group that defined JSR 356 wanted to define some common patterns and techniques to handle the WebSocket communication.

Let’s see with a basic example, which shows how a JavaScript WebSocket client communicates with a Server running Wildfly 8.

<html>
    <head>
        <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
    </head>

    <body>
        <meta charset="utf-8">
        <title>HelloWorld Web sockets</title>
        <script language="javascript" type="text/javascript">
            var wsUri = getRootUri() + "/websocket-hello/hello";

            function getRootUri() {
                return "ws://" + (document.location.hostname == "" ? "localhost" : document.location.hostname) + ":" +
                        (document.location.port == "" ? "8080" : document.location.port);
            }

            function init() {
                output = document.getElementById("output");
            }

            function send_message() {

                websocket = new WebSocket(wsUri);
                websocket.onopen = function(evt) {
                    onOpen(evt)
                };
                websocket.onmessage = function(evt) {
                    onMessage(evt)
                };
                websocket.onerror = function(evt) {
                    onError(evt)
                };

            }

            function onOpen(evt) {
                writeToScreen("Connected to Endpoint!");
                doSend(textID.value);

            }

            function onMessage(evt) {
                writeToScreen("Message Received: " + evt.data);
            }

            function onError(evt) {
                writeToScreen('<span style="color: red;">ERROR:</span> ' + evt.data);
            }

            function doSend(message) {
                writeToScreen("Message Sent: " + message);
                websocket.send(message);
            }

            function writeToScreen(message) {
                var pre = document.createElement("p");
                pre.style.wordWrap = "break-word";
                pre.innerHTML = message;
                 
                output.appendChild(pre);
            }

            window.addEventListener("load", init, false);

        </script>

        <h1 style="text-align: center;">Hello World WebSocket Client</h2>

        <br>

        <div style="text-align: center;">
            <form action="">
                <input onclick="send_message()" value="Send" type="button">
                <input id="textID" name="message" value="Hello WebSocket!" type="text"><br>
            </form>
        </div>
        <div id="output"></div>
</body>
</html>

As you can see, in order to communicate using the WebSocket protocol, you need to create a WebSocket object; this will automatically attempt to open the connection to the server.

 websocket = new WebSocket(wsUri);

Opening a connection will result in the following event which is triggered once the connection is opened:

 websocket.onopen = function(evt) {
        onOpen(evt)
 }; 

Within the onOpen callback method, a message is sent to the Server Endpoint containing barely an Hello world string:

  websocket.send(message);

 


Coding the WebSockets server endpoint

As far as the Server Endpoint is concerned you can use two different programming:

  • Annotation-driven: Using annotated POJOs, developers can interact with the WebSocket lifecycle events.
  • Interface-driven: Developers can implement the Endpoint interface and the methods that interact with the lifecycle events.

In our example we will use the Annotation-Driven approach so an endpoint that is accepting incoming WebSocket requests can be a POJO annotated with the @ServerEndpoint annotation. This annotation tells the container that the given class should be considered to be a WebSocket endpoint. The required value element specifies the path of the WebSocket endpoint.

package com.sample.websocket;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;

 
@ServerEndpoint("/hello")
public class HelloWorldEndpoint {

    
    @OnMessage
    public String hello(String message) {
        System.out.println("Received : "+ message);
        return message;
    }

    @OnOpen
    public void myOnOpen(Session session) {
        System.out.println("WebSocket opened: " + session.getId());
    }

    @OnClose
    public void myOnClose(CloseReason reason) {
        System.out.println("Closing a WebSocket due to " + reason.getReasonPhrase());
    }

}

 
Note: additionally this example contains two other callback methods: one bearing the @OnOpen annotation which is triggered when the WebSocket connection is started (just like the Javascript counterpart) and receiving as parameter the Web Session and another one carrying the @OnClose annotation which is obviously triggered when the connection is closed.

That’s all. In order to compile this simple WebSocket application you need the Websockets API which are currently part of the WildFly 8 distribution in:

modules\system\layers\base\javax\websocket\api\main\jboss-websocket-api_1.0_spec-1.0.0.Final.jar				

For Maven users, all you need to include as dependency is the undertow-websockets-jsr artifact which needs the latest Wildfly 8 Webserver whose name is Undertow:

 <dependencies>
        <dependency>

             <groupId>org.jboss.spec.javax.websocket</groupId>
             <artifactId>jboss-websocket-api_1.0_spec</artifactId>
             <version>1.0.0.Final</version>
        </dependency>

</dependencies>