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
}
}