Usando WebSockets
Este guia explica como seu aplicativo Quarkus pode utilizar web sockets para criar aplicativos web interativas. Por ser a aplicação canônica de web socket, vamos criar um aplicativo de bate-papo simples.
Pré-requisitos
Para concluir este guia, você precisa:
-
Cerca de 15 minutos
-
Um IDE
-
JDK 11+ instalado com 'JAVA_HOME' configurado adequadamente
-
Apache Maven 3.8.6
-
Opcionalmente, o Quarkus CLI se você quiser usá-lo
-
Opcionalmente, Mandrel ou GraalVM instalado e configurado apropriadamente se você quiser criar um executável nativo (ou Docker se você usar uma compilação de contêiner nativo)
Arquitetura
Neste guia, criamos um aplicativo de bate-papo simples usando soquetes da Web para receber e enviar mensagens a outros usuários conectados.

Solução
Recomendamos que você siga as instruções nas próximas seções e crie o aplicativo passo a passo. No entanto, você pode pular diretamente para o exemplo completo.
Clone o repositório Git: git clone https://github.com/quarkusio/quarkus-quickstarts.git, ou baixe um arquivo.
The solution is located in the websockets-quickstart directory.
Criar o projeto Maven
Primeiro, precisamos de um novo projeto. Crie um novo projeto com o seguinte comando:
Esse comando gera o projeto (sem nenhuma classe) e importa a extensão websockets .
Se você já configurou seu projeto Quarkus, pode adicionar a extensão websockets ao seu projeto executando o seguinte comando no diretório base do seu projeto:
quarkus extension add 'websockets'
./mvnw quarkus:add-extension -Dextensions='websockets'
./gradlew addExtension --extensions='websockets'
Isto irá adicionar o seguinte trecho no seu arquivo de build:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-websockets</artifactId>
</dependency>
implementation("io.quarkus:quarkus-websockets")
Se você deseja utilizar apenas o cliente WebSocket, você deve incluir quarkus-websockets-client.
|
Manuseio de web sockets
Nosso aplicativo contém uma única classe que lida com os Web Sockets. Crie a classe org.acme.websockets.ChatSocket no diretório src/main/java . Copie o seguinte conteúdo para o arquivo criado:
package org.acme.websockets;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.enterprise.context.ApplicationScoped;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import javax.websocket.Session;
@ServerEndpoint("/chat/{username}") (1)
@ApplicationScoped
public class ChatSocket {
Map<String, Session> sessions = new ConcurrentHashMap<>(); (2)
@OnOpen
public void onOpen(Session session, @PathParam("username") String username) {
sessions.put(username, session);
}
@OnClose
public void onClose(Session session, @PathParam("username") String username) {
sessions.remove(username);
broadcast("User " + username + " left");
}
@OnError
public void onError(Session session, @PathParam("username") String username, Throwable throwable) {
sessions.remove(username);
broadcast("User " + username + " left on error: " + throwable);
}
@OnMessage
public void onMessage(String message, @PathParam("username") String username) {
if (message.equalsIgnoreCase("_ready_")) {
broadcast("User " + username + " joined");
} else {
broadcast(">> " + username + ": " + message);
}
}
private void broadcast(String message) {
sessions.values().forEach(s -> {
s.getAsyncRemote().sendObject(message, result -> {
if (result.getException() != null) {
System.out.println("Unable to send message: " + result.getException());
}
});
});
}
}
| 1 | Configure a URL do Web Socket |
| 2 | Armazena os web sockets atualmente abertos |
Um frontend da Web sofisticado
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.
Executar o aplicativo
Agora, vamos ver nosso aplicativo em ação. Execute-o com:
quarkus dev
./mvnw quarkus:dev
./gradlew --console=plain quarkusDev
Em seguida, abra as duas janelas do navegador em http://localhost:8080/:
-
Digite um nome na área de texto superior (use dois nomes diferentes).
-
Clique em conectar
-
Enviar e receber mensagens

Como de costume, a aplicação pode ser empacotada utilizando:
quarkus build
./mvnw install
./gradlew build
E executada com java -jar target/quarkus-app/quarkus-run.jar.
Você também pode criar o executável nativo usando:
quarkus build --native
./mvnw install -Dnative
./gradlew build -Dquarkus.package.type=native
You can also test your web socket applications using the approach detailed here.
Clientes WebSocket
O Quarkus também contém um cliente WebSocket. Você pode chamar ContainerProvider.getWebSocketContainer().connectToServer para criar uma conexão WebSocket. Por padrão, o artefato quarkus-websockets inclui suporte tanto para cliente quanto para servidor. No entanto, se você deseja apenas o cliente, pode incluir quarkus-websockets-client.
When you connect to the server you can either pass in the Class of the annotated client endpoint you want to use, or an instance of javax.websocket.Endpoint. If you
are using the annotated endpoint then you can use the exact same annotations as you can on the server, except it must be annotated with @ClientEndpoint instead of
@ServerEndpoint.
O exemplo abaixo mostra o client sendo usado para testar o endpoint de bate-papo acima.
package org.acme.websockets;
import java.net.URI;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;
import javax.websocket.ClientEndpoint;
import javax.websocket.ContainerProvider;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import io.quarkus.test.common.http.TestHTTPResource;
import io.quarkus.test.junit.QuarkusTest;
@QuarkusTest
public class ChatTest {
private static final LinkedBlockingDeque<String> MESSAGES = new LinkedBlockingDeque<>();
@TestHTTPResource("/chat/stu")
URI uri;
@Test
public void testWebsocketChat() throws Exception {
try (Session session = ContainerProvider.getWebSocketContainer().connectToServer(Client.class, uri)) {
Assertions.assertEquals("CONNECT", MESSAGES.poll(10, TimeUnit.SECONDS));
Assertions.assertEquals("User stu joined", MESSAGES.poll(10, TimeUnit.SECONDS));
session.getAsyncRemote().sendText("hello world");
Assertions.assertEquals(">> stu: hello world", MESSAGES.poll(10, TimeUnit.SECONDS));
}
}
@ClientEndpoint
public static class Client {
@OnOpen
public void open(Session session) {
MESSAGES.add("CONNECT");
// Send a message to indicate that we are ready,
// as the message handler may not be registered immediately after this callback.
session.getAsyncRemote().sendText("_ready_");
}
@OnMessage
void message(String msg) {
MESSAGES.add(msg);
}
}
}
Mais informações sobre o WebSocket
A implementação do Quarkus WebSocket é uma implementação do Jakarta Websockets .