Quarkus - Using WebSockets

This guide explains how your Quarkus application can utilize web sockets to create interactive web applications. Because it’s the canonical web socket application, we are going to create a simple chat application.

Prerequisites

To complete this guide, you need:

  • less than 15 minutes

  • an IDE

  • JDK 1.8+ installed with JAVA_HOME configured appropriately

  • Apache Maven 3.6.2+

Architecture

In this guide, we create a straightforward chat application using web sockets to receive and send messages to the other connected users.

Architecture

Solution

We recommend that you follow the instructions in the next sections and create the application step by step. However, you can skip right to the completed example.

Clone the Git repository: git clone [https://github.com/quarkusio/quarkus-quickstarts.git](https://github.com/quarkusio/quarkus-quickstarts.git), or download an archive.

The solution is located in the websockets-quickstart directory.

Creating the Maven project

First, we need a new project. Create a new project with the following command:

  1. mvn io.quarkus:quarkus-maven-plugin:1.7.6.Final:create \
  2. -DprojectGroupId=org.acme \
  3. -DprojectArtifactId=websockets-quickstart \
  4. -Dextensions="undertow-websockets"
  5. cd websockets-quickstart

This command generates the Maven project (without any classes) and import the undertow-websockets extension.

If you already have your Quarkus project configured, you can add the undertow-websockets extension to your project by running the following command in your project base directory:

  1. ./mvnw quarkus:add-extension -Dextensions="undertow-websockets"

This will add the following to your pom.xml:

  1. <dependency>
  2. <groupId>io.quarkus</groupId>
  3. <artifactId>quarkus-undertow-websockets</artifactId>
  4. </dependency>

Handling web sockets

Our application contains a single class that handles the web sockets. Create the org.acme.websockets.ChatSocket class in the src/main/java directory. Copy the following content into the created file:

  1. package org.acme.websockets;
  2. import java.util.Map;
  3. import java.util.concurrent.ConcurrentHashMap;
  4. import javax.enterprise.context.ApplicationScoped;
  5. import javax.websocket.OnClose;
  6. import javax.websocket.OnError;
  7. import javax.websocket.OnMessage;
  8. import javax.websocket.OnOpen;
  9. import javax.websocket.server.PathParam;
  10. import javax.websocket.server.ServerEndpoint;
  11. import javax.websocket.Session;
  12. @ServerEndpoint("/chat/{username}") (1)
  13. @ApplicationScoped
  14. public class ChatSocket {
  15. Map<String, Session> sessions = new ConcurrentHashMap<>(); (2)
  16. @OnOpen
  17. public void onOpen(Session session, @PathParam("username") String username) {
  18. sessions.put(username, session);
  19. broadcast("User " + username + " joined");
  20. }
  21. @OnClose
  22. public void onClose(Session session, @PathParam("username") String username) {
  23. sessions.remove(username);
  24. broadcast("User " + username + " left");
  25. }
  26. @OnError
  27. public void onError(Session session, @PathParam("username") String username, Throwable throwable) {
  28. sessions.remove(username);
  29. broadcast("User " + username + " left on error: " + throwable);
  30. }
  31. @OnMessage
  32. public void onMessage(String message, @PathParam("username") String username) {
  33. broadcast(">> " + username + ": " + message);
  34. }
  35. private void broadcast(String message) {
  36. sessions.values().forEach(s -> {
  37. s.getAsyncRemote().sendObject(message, result -> {
  38. if (result.getException() != null) {
  39. System.out.println("Unable to send message: " + result.getException());
  40. }
  41. });
  42. });
  43. }
  44. }
  1. Configures the web socket URL

  2. Stores the currently opened web sockets

A slick web frontend

All chat applications need a nice UI, well, this one may not be that nice, but does the work. Quarkus automatically serves static resources contained in the META-INF/resources directory. Create the src/main/resources/META-INF/resources directory and copy this index.html file in it.

Run the application

Now, let’s see our application in action. Run it with:

  1. ./mvnw compile quarkus:dev

Then open your 2 browser windows to http://localhost:8080/:

  1. Enter a name in the top text area (use 2 different names).

  2. Click on connect

  3. Send and receive messages

Application

As usual, the application can be packaged using ./mvnw clean package and executed using the -runner.jar file. You can also build the native executable using ./mvnw package -Pnative.

You can also test your web socket applications using the approach detailed here.