diff --git a/.github/quarkus-bot.yml b/.github/quarkus-bot.yml
index d2a1022004829..5471c4e5232ec 100644
--- a/.github/quarkus-bot.yml
+++ b/.github/quarkus-bot.yml
@@ -454,6 +454,7 @@ triage:
- labels: [area/websockets]
directories:
- extensions/websockets/
+ - integration-tests/websockets/
- labels: [area/swagger-ui]
title: "swagger"
notify: [phillip-kruger, MikeEdgar]
diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml
index 18a59941671eb..c26675671df17 100644
--- a/integration-tests/pom.xml
+++ b/integration-tests/pom.xml
@@ -188,6 +188,7 @@
vertx-web
vertx-web-jackson
vertx
+ websockets
spring-di
spring-web
spring-data-jpa
diff --git a/integration-tests/websockets/pom.xml b/integration-tests/websockets/pom.xml
new file mode 100644
index 0000000000000..251aa582868cd
--- /dev/null
+++ b/integration-tests/websockets/pom.xml
@@ -0,0 +1,87 @@
+
+
+ 4.0.0
+
+
+ quarkus-integration-tests-parent
+ io.quarkus
+ 999-SNAPSHOT
+
+
+ quarkus-integration-test-websockets
+ Quarkus - Integration Tests - WebSockets
+
+
+
+ io.quarkus
+ quarkus-websockets
+
+
+ io.quarkus
+ quarkus-arc
+
+
+
+ io.quarkus
+ quarkus-junit5
+ test
+
+
+ io.rest-assured
+ rest-assured
+ test
+
+
+ org.awaitility
+ awaitility
+ test
+
+
+
+
+ io.quarkus
+ quarkus-arc-deployment
+ ${project.version}
+ pom
+ test
+
+
+ *
+ *
+
+
+
+
+ io.quarkus
+ quarkus-websockets-deployment
+ ${project.version}
+ pom
+ test
+
+
+ *
+ *
+
+
+
+
+
+
+
+
+ io.quarkus
+ quarkus-maven-plugin
+
+
+
+ build
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/integration-tests/websockets/src/main/java/io/quarkus/websockets/ChatServer.java b/integration-tests/websockets/src/main/java/io/quarkus/websockets/ChatServer.java
new file mode 100644
index 0000000000000..85f942748f91d
--- /dev/null
+++ b/integration-tests/websockets/src/main/java/io/quarkus/websockets/ChatServer.java
@@ -0,0 +1,57 @@
+package io.quarkus.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.Session;
+import javax.websocket.server.PathParam;
+import javax.websocket.server.ServerEndpoint;
+
+@ServerEndpoint("/chat/{username}")
+@ApplicationScoped
+public class ChatServer {
+
+ Map sessions = new ConcurrentHashMap<>();
+
+ @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());
+ }
+ });
+ });
+ }
+
+}
diff --git a/integration-tests/websockets/src/test/java/io/quarkus/websockets/ChatTest.java b/integration-tests/websockets/src/test/java/io/quarkus/websockets/ChatTest.java
new file mode 100644
index 0000000000000..9f81fdc9a52d2
--- /dev/null
+++ b/integration-tests/websockets/src/test/java/io/quarkus/websockets/ChatTest.java
@@ -0,0 +1,55 @@
+package io.quarkus.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 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);
+ }
+
+ }
+
+}
\ No newline at end of file