About Ibrahim Tasyurt

Ibrahim is a Senior Software Engineer residing in Ankara,Turkey. He holds BSc and MS degrees in Computer Engineering from Middle East Technical University(METU). Throughout his professional carrier, he has worked in Enterprise Web Application projects for public sector and telecommunications domains. Java EE, Web Services and Enterprise Application Integration are the areas he is primarily involved with.

Jetty WebSocket Example

1.Introduction

This article is about WebSockets with Jetty. In this example we will give brief information on WebSockets and show how to implement WebSocket Servers and Clients using Jetty WebSocket APIs. In addition to these, an example HTML+JavaScript client interacting with the Server through WebSockets will be provided.

2.WebSockets

WebSocket is a standard protocol facilitating full-duplex communication over a single TCP socket. The protocol is designed primarily for Web Browsers and Web Servers however it can be applied to other server-client integration cases.

The concept of WebSockets has been emerged due to the limitations of HTTP. HTTP is a pull based (request-response) protocol; which means that server cannot directly push messages to the client. The alternatives aiming to tackle this problem (TCP sockets, Comet, Long-polling etc.) provide workaround solutions causing side effects of their own.

WebSocket protocol is based on existing web application technologies. A WebSocket connection utilizes the same port with the application server(80 or 8080 for instance), hence it is less likely to be blocked by firewalls. WebSocket connection between client and server is established by a handshake through an HTTP upgrade request. After successful handshake, the protocol is switched from HTTP to WebSocket.

Want to master Jetty?

Subscribe to our newsletter and download the Jetty Server Cookbook right now!

In order to get you prepared for your Jetty development needs, we have compiled numerous recipes to help you kick-start your projects. Besides reading them online you may download the eBook in PDF format!

Email address:

Leave this field empty if you're human:

WebSocket defines two prefixes for the server URI.

ws: for unsecure connections

Example: ws://example.codegeeks.com/websocketExample

wss: for secure connections

Example: wss://example.codegeeks.com/websocketExample

For the browser based applications, WebSocket protocol support has to be provided by the browser. Currently WebSockets are supported by almost all modern browsers including Chrome, Firefox, Internet Explorer and Safari.

Today WebSockets are widely used in the cases that servers need to push data to the web clients (online gaming, chat).

3.Jetty WebSocket APIs

WebSocket technology needs to be supported not only on the browser but also on the server side. Different platforms do have their own implementation for WebSockets both for server and client roles. Jetty is one of the platforms providing WebSocket API for both server and clients sides.

Jetty implements two alternative APIs for WebSocket development:

First of them is the JSR-356 compliant one. JSR-356 is the Java API for WebSocket specification which is included in Java EE 7. The spec defines an annotation based API as well as an listener interface based one.

The other alternative is Jetty’s own implementation: Jetty WebSocket API. This API had emerged before JSR-356 was released. The programming model of Jetty WebSocket API is very similar to JSR-356 based one. It also provides similar annotations and listener interfaces.

In the following subsections we expand on both alternatives.

3.1 Alternative 1: Jetty JSR-356 Implementation

JSR-356 has two different approaches for WebSocket implementation: One is Annotations based whereas the other is Interface based. In the Annotations approach, you have to decorate your POJOs with relevant annotations of the API. In the Interface approach, you need to implement the WebSocket Endpoint interface.

Both approaches are similar. The annotations in the first approach match to the methods to be implemented in the Interface approach. Here we explain only the annotations.

@ServerEndpoint:

ServerEndpoint is used to annotate a POJO classes as server side WebSockets. The value of the annotation determines the URL path of the WebSocket(similar to the servlet mappings in Java web applications):

An example can be seen below:

@ServerEndpoint(value = "/example")
public class MySocket{
…}

@ClientEndpoint:

ServerEndpoint is used to annotate a POJO classes as client side WebSockets.

@ClientEndpoint
public class MySocket{
…}

@OnOpen:

OnOpen annotates the method that handles the event when a connection is established. JSR-356 does not mandate anything on naming of annotated methods, so we can name our methods as we like.

@OnOpen
public void onSessionOpened(Session session){
}

Session is the class that encapsulates the Socket connection session.

@OnMessage:

OnMessage is used to annotate the method that handles the incoming messages.

CloseReason is a class that encapsulates the termination reason along with a code.

@OnError:

OnError annotation defines the method that handles exceptions. An example usage is as follows:

@OnError
public void onErrorReceived(Throwable t) {
}

ServerEndpoint is applicable on server side whereas ClientEndpoint is applicable only on client side. Other annotations are applicable for both sides.

A last remark is that, the signatures (parameter and return types) of the annotated methods must be one of the signatures allowed by JSR-356. The examples presented above are legal according to the spec. JavaDoc presents the allowed method signatures for each annotation.

3.2 Alternative 2: Jetty WebSocket API Implementation

In addition to JSR-356 support, Jetty also provides its own API. The reason that Jetty has two APIs on WebSockets is that JSR-356 was released after Jetty had released its own. JSR-356 API is heavily inspired by Jetty’s.

From the developer’s point of view Jetty API is very similar to the JSR-356’s, with minor differences.

Jetty WebSocket API needs initialization of a Servlet which extends org.eclipse.jetty.websocket.servlet.WebSocketServlet class. In JSR-356 implementation this is not needed. In this servlet, we configure the servlet socket class, which resembles the annotated Server Socket class implementation of JSR-356.

In the Example section, we will show how we can configure this server socket at the Servlet implementation.

Adapter Based: A convenience approach which eases Listener based implementation.

The easiest way is the Annotation approach. The annotation names (and classes) are different than JSR-356’s however they are almost of the same use.

@WebSocket

This annotation defines that the class is a WebSocket server. It is similar to the @ServletEndpoint of JSR-356 but we do not give the endpoint URL here. In addition to this, this annotation is not specific to the server side. Socket clients are also marked with this annotation.

@WebSocket
public class ExampleWebSocket{
}

@OnWebSocketConnect

This annotation defines that the method to be invoked when a connection is opened. It is similar to @OnOpen of JSR-356.

@OnWebSocketConnect
public void onConnect(Session session){
}

@OnWebSocketMessage

This annotation defines that the method to be invoked when a message is received. It is similar to @OnMessage of JSR-356.

@OnWebSocketError

This annotation defines that the method to be invoked when a connection related error is thrown. It is similar to @OnError of JSR-356.

@OnWebSocketError
public void onError(Throwable error){
}

Similar to the JSR-356, the method names are not mandated by Jetty in this approach. The full list of allowed parameter types can be viewed in Jetty documentation.

3.3 Which API to Choose?

Both APIs offer similar features and programming approach. However there are subtle differences.

JSR-356 is specification based and standard. You can port easily your server sockets from Jetty to another Servlet container or Application server as long as the server supports JSR-356. In addition to this, programming with this API is a bit simpler. You do not need to configure a servlet with JSR-356 API. The downside of this alternative is, the documentation on Jetty side is missing and it seems less mature than the second alternative (but that might be just an impression).

Jetty WebSocket API is not standard, so you have to change your code when you change your Servlet Container. In addition to this, you have to code the servlet (some piece of boilerplate code) yourself. But Jetty API is more flexible allowing to easier control timeouts, paths, SSL etc. Another advantage is that, Jetty documentation of its own API is better than Jetty documentation on JSR-356.

At this point, I would humbly recommend using JSR-356 API if simpler configuration matters to you or if portability is a major concern. If you need to configure WebSocket parameters in detail and you do not need to port your WebSocket to another container, I would recommend Jetty WebSocket API.

Of course, this portability issue is only about porting WebSocket code from one container to another (from Jetty to Tomcat for example). WebSocket is a standardized protocol, so any kind of WebSocket client connect to any implementation (JSR compliant or not) server without a problem.

In the following section we will provide examples of both APIs for server and client sides.

4.Example

In the example, we will first start with a simple WebSocket Server implementation that gets a text message from the client and echoes back converting the message to uppercase. We will provide both JSR-356 and Jetty API versions of these server side WebSocket implementations.

Later we will move on to the client part. We will implement a Java WebSocket clients interacting with this WebSocket server (again both JSR-356 based and Jetty API versions). Thereafter, we will provide another client example this time with HTML + JavaScript.

4.1 Environment

For the example, following programming environment is used:

For the Jetty WebSocket Server:

Java 7

Maven 3.x.y

Maven Jetty Plugin

Eclipse Luna as the IDE

For the the Jetty WebSocket Client:

Java 7

Maven 3.x.y

Eclipse Luna as the IDE

For the HTML WebSocket Client

A browser supporting WebSockets (Firefox 38.0.5 in this example)

Eclipse Luna as the IDE (used as HTML editor)

In this example, we will create a single Maven project in Eclipse and run it as a web application for the servers. The Java clients will be run as console applications and the HTML client will be deployed on the web application.

4.2 Creating the Maven Project

In order to create the Maven project on Eclipse, you can follow the steps below:

Go to File -> New ->Other -> Maven Project

Tick “Create a simple project” and press “Next”.

Enter groupId as : com.javacodegeeks.snippets.enterprise

Enter artifactId as : jetty-websocket-example

Press “Finish”.

Now our Maven project is created.

4.3 Configuring the Maven Dependencies and Jetty Plugin

In order to configure the project, we need following dependencies:

First we need Jetty dependencies:

org.eclipse.jetty.websocket:jetty-server

org.eclipse.jetty.websocket:jetty-servlet

If you are implementing a WebSocket server with JSR-356 API we need:

org.eclipse.jetty.websocket:javax-websocket-server-impl

If we choose, Jetty API for WebSocket server we need:

org.eclipse.jetty.websocket:websocket-server

For the client side implementation we choose one of the following depending on we choose JSR-356 or the Jetty alternative:

org.eclipse.jetty.websocket:javax-websocket-client-impl

org.eclipse.jetty.websocket:websocket-client

The version we have used in this example is 9.2.11.v20150529.

In this example, we have added all of these dependencies to our pom.xml. Depending on the approach you choose, you can remove the unnecessary ones based on your your need.

You might have noticed that there is a CountDownLatch that is counted down when the connection is open. This latch is only for convenience in order to block other part of the client code before the connection is open. In addition to this, we added a public void sendMessage() method to send messages to the server.

Until now, we have created the WebSocket; the missing part is the code driving the client and initiating the contact. The snippet to initiate the connection can be seen below:

Here the session object is of type org.eclipse.jetty.websocket.api.Session and sending messages to the client is performed with following method call:

session.getRemote().sendString("echo!");

As you see, there is not much difference between JSR-356 API and Jetty’s up-to here except we did not configure the URL path in the WebSocket class. Now we will configure it via a Servlet.

The main difference of Jetty WebSocket API is that we have to implement a Servlet extending WebSocketServlet class. In this servlet, we define the URL pattern to be matched and we configure WebSocket class handling the requests to this URL. A minimal servlet implementation is here:

Connected to server
Message received from server:ECHO
Message received from server:TEST

4.8 HTML Client Example

Java based client for a WebSocket is convenient for some cases but the core use of WebSockets is ability to push data from servers to browsers. In this part, we will create a simple HTML page connecting to the WebSocket server in order to demonstrate browser to server integration.

This example page has three functionalities:

User shall connect to the server.

User shall send messages to the server.

User shall see the received messages on the server.

On this purpose, there are two buttons on the page. One is to CONNECT, one is to SEND messages. In addition to these, there is a text input area and an output div in the HTML page.

When the user clicks the CONNECT button, following JavaScript code executes connecting to the server.

As you see, unlike HTTP the type of interaction with WebSockets is duplex; we can simultaneously send and receive data. In HTTP, we would have to initiate an HTTP request and wait for the response to receive data from the server.

Please note that the HTML +JavaScript code are for simple demonstration purpose only. There are many better development practices and libraries for front-end development.

5.Conclusion

WebSocket is a technology tackling the shortcomings of the HTTP for bidirectional duplex communication. It is a trending topic that is becoming more widespread. In this post, we have strived to provide brief information on WebSockets and we have provided example Server and Client side implementations of WebSockets using WebSocket API of Jetty.

Newsletter

Join them now to gain exclusive access to the latest news in the Java world, as well as insights about Android, Scala, Groovy and other related technologies.

Email address:

Receive Java & Developer job alerts in your Area

Leave this field empty if you're human:

Join Us

With 1,240,600 monthly unique visitors and over 500 authors we are placed among the top Java related sites around. Constantly being on the lookout for partners; we encourage you to join us. So If you have a blog with unique and interesting content then you should check out our JCG partners program. You can also be a guest writer for Java Code Geeks and hone your writing skills!

Disclaimer

All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners. Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries. Examples Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.