Previous Topic

Next Topic

Book Contents

Book Index

Implementing Server Endpoint

To handle incoming Websocket connections, developers should implement and register a server endpoint.

Server endpoint is implemented by annotating a Plain Old Java Object (POJO) with javax.websocket.server.ServerEndpoint annotation.

The annotate class should have a public default constructor:

import javax.websocket.server.ServerEndpoint;

@ServerEndpoint("/ws/demo")

public class DemoEndpoint {

...

}

Aside from the endpoint path, which is a required parameter, additionally accepted sub-protocols and ServerEndpointConfig.Configurator can be specified through @ServerEndpoint annotation. ServerEndpointConfig.Configurator can be used to customize endpoint instances creation, sub-protocol negotiation, modify handshake, etc.

The Websocket container will create instances of this class to handle incoming websocket connections (to path "/ws/demo" in the example above). A single instance of the server endpoint class will be created for each incoming connection. This behavior can be overridden by using ServerEndpointConfig.Configurator.

Connection life-cycle events can be handled by public methods decorated with @OnOpen / @OnClose annotations:

import javax.websocket.OnOpen;

import javax.websocket.OnClose;

import javax.websocket.Session;

...

  @OnOpen

  public void onOpen(Session session) {

    System.out.println("Websocket opened: " + session.getId());

  }

  @OnClose

  public void onClose(CloseReason reason) {

    System.out.println("Websocket closed: " + reason);

  }

  ...

The OnOpen method can have as optional input parameters the websocket session, endpoint config and zero or more path parameters. The OnClose method can take the session, close reason and path parameters. For details refer to annotations JavaDoc.

The @OnError annotation can be used to specify a method to be called to handle errors arising during the endpoint life-cycle:

import javax.websocket.OnError;

...

  @OnError

  public void onError(Session session, Throwable ex) {

    System.err.println("Websocket error: " + session.getId());

    ex.printStackTrace();

  }

...

Message handling is handled by public method annotated with @OnMessage annotation:

import javax.websocket.OnMessage;

...

  @OnMessage

  public String onMessage(String message) {

    System.out.println("Websocket message received: " + message);

    return message.toUpperCase(); // response to client

  }

...

In the example above, the server endpoint receives a test message and immediately responds to the client with the same message, but in upper case. The OnMessage method can handle text, binary or pong messages – for details refer to javax.websocket.OnMessage JavaDoc.

The OnMessage method can have a non-void return type, which will be interpreted as a message to be sent to the client.

The supported message parameter types are:

Handling messages as Reader, InputStream or object with defined Encoder/Decoder is not supported in the current release.

A message can be sent to the client either as in the example above:

Full demo server endpoint source:

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("/ws/demo")

public class DemoEndpoint {

  @OnOpen

  public void onOpen(Session session) {

    System.out.println("Websocket opened: " + session.getId());

  }

  @OnClose

  public void onClose(CloseReason reason) {

    System.out.println("Websocket closed: " + reason);

  }

  @OnError

  public void onError(Session session, Throwable ex) {

    System.err.println("Websocket error: " + session.getId());

    ex.printStackTrace();

  }

  @OnMessage

  public String onMessage(String message) {

    System.out.println("Websocket message received: " + message);

    return message.toUpperCase(); // response to client

  }

}