Table of Contents
This chapter provides a quick introduction on how to get started building WebSocket services using Java API for WebSocket and Tyrus. The example described here presents how to implement simple websocket service as JavaEE web application that can be deployed on any servlet container supporting Servlet 3.1 and higher. It also discusses starting Tyrus in standalone mode.
First, to use the Java API for WebSocket in your project you need to depend on the following artifact:
<dependency> <groupId>javax.websocket</groupId> <artifactId>javax.websocket-api</artifactId> <version>1.1.1</version> </dependency>
In this section we will create a simple server side websocket endpoint which will echo the received message back to the sender. We will deploy this endpoint on the container.
In Java API for WebSocket and Tyrus, there are two basic approaches how to create an endpoint - either annotated endpoint,
or programmatic endpoint.
By annotated endpoint we mean endpoint constructed by using annotations (javax.websocket.server.ServerEndpoint
for server endpoint and javax.websocket.ClientEndpoint
for client endpoint), like in
"Annotated Echo Endpoint".
Example 1.1. Annotated Echo Endpoint
@ServerEndpoint(value = "/echo") public class EchoEndpointAnnotated { @OnMessage public String onMessage(String message, Session session) { return message; } }
The functionality of the EchoEndpointAnnotated
is fairly simple - to send the received message
back to the sender. To turn a POJO (Plain Old Java Object) to WebSocket server endpoint, the annotation
@ServerEndpoint(value = "/echo")
needs to be put on the POJO - see line 1. The URI path of the endpoint
is "/echo"
. The annotation @OnMessage
- line 3 on the method public String
onMessage(String message, Session session)
indicates that this method
will be called whenever text message is received. On line 5 in this method the message is sent back to
the user by returning it from the message.
The application containing only the EchoEndpointAnnotated
class can be deployed to the container.
Let's create the client part of the application. The client part may be written in JavaScript or any
other technology supporting WebSockets. We will use Java API for WebSocket and Tyrus to demonstrate how to develop
programmatic client endpoint.
The following code is used as a client part to communicate with the EchoEndpoint
deployed on server
using Tyrus and Java API for WebSocket.
The example "Client Endpoint" utilizes the concept
of the programmatic endpoint. By programmatic endpoint we mean endpoint which is created by extending
class javax.websocket.Endpoint
.
The example is standalone java application which needs to depend on some Tyrus artifacts to work
correctly, see "Tyrus Standalone Mode".
In the example first the CountDownLatch
is initialized. It is needed as a bocking data
structure - on line 31 it either waits for 100 seconds, or until it gets counted down (line 22).
On line 9 the javax.websocket.ClientEndpointConfig
is created - we will need it later
to connect the endpoint to the server. On line 11 the org.glassfish.tyrus.client.ClientManager
is created. it implements the javax.websocket.WebSocketContainer
and is used to connect
to server. This happens on next line. The client endpoint functionality is contained in the
javax.websocket.Endpoint
lazy instantiation. In the onOpen
method new MessageHandler
is registered (the received message is just printed on the console and the latch is counted down). After
the registration the message is sent to the server (line 25).
Example 1.2. Client Endpoint
public class DocClient { private static CountDownLatch messageLatch; private static final String SENT_MESSAGE = "Hello World"; public static void main(String [] args){ try { messageLatch = new CountDownLatch(1); final ClientEndpointConfig cec = ClientEndpointConfig.Builder.create().build(); ClientManager client = ClientManager.createClient(); client.connectToServer(new Endpoint() { @Override public void onOpen(Session session, EndpointConfig config) { try { session.addMessageHandler(new MessageHandler.Whole<String>() { @Override public void onMessage(String message) { System.out.println("Received message: "+message); messageLatch.countDown(); } }); session.getBasicRemote().sendText(SENT_MESSAGE); } catch (IOException e) { e.printStackTrace(); } } }, cec, new URI("ws://localhost:8025/websockets/echo")); messageLatch.await(100, TimeUnit.SECONDS); } catch (Exception e) { e.printStackTrace(); } } }
Similarly to "Client Endpoint" the server registered endpoint may also be the programmatic one:
Example 1.3. Programmatic Echo Endpoint
public class EchoEndpointProgrammatic extends Endpoint { @Override public void onOpen(final Session session, EndpointConfig config) { session.addMessageHandler(new MessageHandler.Whole<String>() { @Override public void onMessage(String message) { try { session.getBasicRemote().sendText(message); } catch (IOException e) { e.printStackTrace(); } } }); } }
The functionality of the EchoEndpointProgrammatic
is fairly simple - to send the received message back to the sender.
The programmatic server endpoint needs to extend javax.websocket.Endpoint
- line 1.
Mehod public void onOpen(final Session session, EndpointConfig config)
gets called once new
connection to this endpoin0t is opened. In this method the MessageHandler
is registered to the
javax.websocket.Session
instance, which opened the connection. Method public void
onMessage(String message)
gets called once the message is received. On line 8 the message
is sent back to the sender.
To see how both annotated and programmatic endpoints may be deployed please check the section Deployment. In short: you need to put the server endpoint classes into WAR, deploy on server and the endpoints will be scanned by server and deployed.
To use Tyrus in standalone mode it is necessary to depend on correct Tyrus artifacts. The following artifacts need to be added to your pom to use Tyrus:
<dependency> <groupId>org.glassfish.tyrus</groupId> <artifactId>tyrus-server</artifactId> <version>1.21</version> </dependency> <dependency> <groupId>org.glassfish.tyrus</groupId> <artifactId>tyrus-container-grizzly-server</artifactId> <version>1.21</version> </dependency>
Let's use the very same example like for Java API for WebSocket and deploy the EchoEndpointAnnotated
on the
standalone Tyrus server on the hostname "localhost", port 8025 and path "/websockets", so the endpoint
will be available at address "ws://localhost:8025/websockets/echo".
public void runServer() { Server server = new Server("localhost", 8025, "/websockets", null, EchoEndpoint.class); try { server.start(); BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); System.out.print("Please press a key to stop the server."); reader.readLine(); } catch (Exception e) { e.printStackTrace(); } finally { server.stop(); } }