Server-side Java WebSockets

In Java EE 7, the Java package javax.websocket is the root for WebSockets. There is one package underneath this one for server endpoints: javax.websocket.server.

The server-side endpoint in Java represents one end of the peers. Java applications with WebSocket endpoints are created through programming directly against the library. Otherwise, the endpoints are determined by annotations in the JSR 356 specification.

The annotation javax.websocket.server.ServerEndpoint is applied to classes that execute an endpoint on the server. The annotation requires a URL pattern fragment similar to the Servlet 3.1 annotation @javax.servlet.WebServlet, which determines how the implementation provider routes an incoming WebSockets request to the endpoint.

We can annotate a POJO so that it will be registered as a server-side WebSocket endpoint, but how can we receive messages from the client? The answer is annotation: @javax.websocket.OnMessage. This annotation declares a particular method to receive messages that arrive on the WebSocket connection.

Let's take a look at a simple echo server example:

package je7hb.websocket.basic;
import javax.websocket.OnMessage;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint("/echo")
public class EchoWebSocketServer {

  @OnMessage
  public String doListen(String message) {
    return "Echo: Got your message (" + message +
      "). Thanks";
  }
}

This is, perhaps, the simplest Java WebSocket server that one can write. The @ServerEndpoint annotation declares the class EchoWebSocketServer as a server-side endpoint in that it is capable of receiving connection requests from clients. The URL pattern "/echo" declares how the WebSocket implementation routes the request to the endpoint.

The method doListen() is annotated with @OnMessage and declares to the implementation what method to invoke when a message has been received on the connection. Note that the return type of the method doListen() is String. It is possible to return a message to the client directly, which is of course exactly the function of the method.

@ServerEndpoint

Let's look at the annotations in detail; here is the table of attributes for the annotations for @javax.websocket.server.ServerEndpoint:

Attribute

Type

Description

Default Value

value

String

Defines the URI or URI template where the endpoint will be deployed. The URI must begin with a character """"/". Trailing """"/" characters are ignored.

None

subProtocols

String []

Defines an ordered array of WebSocket protocols that this endpoint supports.

None

decoders

Decoder[]

Specifies an ordered array of encoder classes this endpoint will use.

None

decoders

Encoder[]

Specifies an ordered array of encoder classes that the endpoint will use.

None

configurator

Class<? Extends ServerEndPoint-Configurator>

Defines a custom configurator that the developer would like to use to configure a logical endpoint instance.

ServerEndpoint-Configuration.class

@OnMessage

Here is the table of attributes for the @javax.websocket.OnMessage:

Attribute

Type

Description

Default Value

maxMessageSize

long

Specifies the maximum size in bytes for the incoming message.

None

There is only one attribute allowed. The maxMessageType attribute sets the maximum size of the message following the successful completion of the initial handshake.

Invoking Java WebSocket

We can define a Java WebSocket endpoint on the server side. There would be no point in defining the WebSocket unless there was a way of calling it. We only require a simple HTML5 and JavaScript web page to do this. WebSockets are supported by most of the modern web browsers: Mozilla Firefox, Google Chrome, Apple Safari, and Microsoft Internet Explorer.

The page that invokes the EchoWebSocketServer looks like the following:

<!DOCTYPE html>
<head>
<meta charset="utf-8"/>
<title>Echo Server Side WebSocket Test</title>
<script language="javascript" type="text/javascript">
  var wsUri = "ws://localhost:8080/mywebapp/echo";
  var output;

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

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

  function onOpen(evt) {
    writeToScreen("CONNECTED");
    doSend("HTML5 Java WebSockets Rocks!");
  }

  function onClose(evt) {
    writeToScreen("DISCONNECTED");
  }

  function onMessage(evt) {
    writeToScreen('<span style="color: blue;">RESPONSE:'
      + evt.data + '</span>'),
    websocket.close();
  }

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

  function doSend(message) {
    writeToScreen("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>
<head>
<body>
<h2>WebSocket Test</h2>
<div id="output"></div>
</body>
</html>

This is mostly an adaption of the code that exists on the HTML5 community website: http://websocket.org/. It is about as simple as it can get for a Hello World example for WebSockets.

The page is mostly JavaScript. There is one h2 header and a div layer element with an id of "output". An event handler init() is registered on the page, as soon as it is loaded with the browser. The first action of the function init() finds the output div layer in the Document Object Model. The second invokes the testWebSocket() function.

The function testWebSocket() creates a WebSocket and then registers callback functions on it on various events. On the JavaScript side, one listens for when the web sockets are opened or closed, or when a message is received, and if there is an error on the channel.

The function onOpen() is a callback function in JavaScript, which is invoked when the WebSocket successfully makes a connection to the remote endpoint, which is in our case the EchoWebSocketServer. The function sends a message down the channel to the server by calling the helper function doSend().

Upon reception of the message on the WebSocket, the JavaScript function onMessage() is invoked. This function appends a new text element with the message to the output div layer by calling the helper function writeToScreen().

Running WebSocket examples

The code that deploys the WebSocket is exactly the same as the EmbeddedRunner in the Servlet chapter. The only difference is the name of the WAR file. We use an embedded GlassFish server instance and deploy a WAR file to it with the WebSockets endpoint. The open source project Tyrus (on Java .Nethttps://java.net/projects/tyrus) is the reference implementation of the Java WebSockets specification inside the GlassFish project. Tyrus is responsible for creating WebSocket endpoints by scanning the WAR file for the appropriate @ServerEndpoint annotations. Once it finds them, the implementation validates the class and then generates configuration around each endpoint, which intercepts the URI template, and then activates the WebSocket for service.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.22.74.160