Skip to content

Commit

Permalink
fix: make sure annotated endpoints works along Vaadin PUSH
Browse files Browse the repository at this point in the history
The workaround added to make PUSH work in Quarkus prevents the usage of custom
annotated websocket endpoint. This change allow them to work along Vaadin PUSH.

Fixes #78
  • Loading branch information
mcollovati committed Sep 30, 2022
1 parent 8b8e795 commit 210ac37
Show file tree
Hide file tree
Showing 12 changed files with 284 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import io.quarkus.vertx.http.deployment.FilterBuildItem;
import io.quarkus.websockets.client.deployment.ServerWebSocketContainerBuildItem;
import io.quarkus.websockets.client.deployment.WebSocketDeploymentInfoBuildItem;
import org.atmosphere.cpr.ApplicationConfig;
import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.AnnotationValue;
import org.jboss.jandex.ClassInfo;
Expand Down Expand Up @@ -144,7 +145,11 @@ void mapVaadinServletPaths(final BeanArchiveIndexBuildItem beanArchiveIndex,
.builder(QuarkusVaadinServlet.class.getName(),
QuarkusVaadinServlet.class.getName())
.addMapping("/*").setAsyncSupported(true)
.setLoadOnStartup(1).build());
.setLoadOnStartup(1)
// TODO: should be fixed in Flow and removed from here
.addInitParam(ApplicationConfig.JSR356_PATH_MAPPING_LENGTH,
"0")
.build());
}
}

Expand Down Expand Up @@ -277,6 +282,9 @@ private Collection<ClassInfo> registerUserServlets(
setAsyncSupportedIfDefined(webServletInstance, servletBuildItem);
servletBuildItem
.setLoadOnStartup(loadOnStartup > 0 ? loadOnStartup : 1);
// TODO: should be fixed in Flow and removed from here
servletBuildItem.addInitParam(
ApplicationConfig.JSR356_PATH_MAPPING_LENGTH, "0");
if (loadOnStartup < 1) {
LOG.warn(
"Vaadin Servlet needs to be eagerly loaded by setting load-on-startup to be greater than 0. "
Expand Down
6 changes: 6 additions & 0 deletions integration-tests/common-test-code/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@
<artifactId>flow-test-util</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>custom-websockets</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>io.quarkus</groupId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.vaadin.flow.quarkus.it;

import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint(CustomAnnotatedEnpoint.URI)
public class CustomAnnotatedEnpoint {

public static final String URI = "/app-annotated-websocket";
public static final String PREFIX = ">> Application Annotated Endpoint: ";

@OnOpen
public void onOpen(Session session) {
session.getAsyncRemote().sendText(PREFIX + "Welcome");
}

@OnMessage
public void onMessage(String message, Session session) {
session.getAsyncRemote().sendText(PREFIX + message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package com.vaadin.flow.quarkus.it;

import javax.websocket.ClientEndpoint;
import javax.websocket.ContainerProvider;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import java.io.IOException;
import java.net.URI;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;

import io.quarkus.test.common.http.TestHTTPResource;
import io.quarkus.test.junit.QuarkusIntegrationTest;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.vaadin.sample.websockets.DependencyAnnotatedWS;
import org.vaadin.sample.websockets.SimpleEndpoint;

@QuarkusIntegrationTest
class CustomWebsocketsIT {

@TestHTTPResource(DependencyAnnotatedWS.URI)
URI dependencyAnnotatedWSURI;

@TestHTTPResource(SimpleEndpoint.URI)
URI dependencyNotAnnotatedWSURI;

@TestHTTPResource(CustomAnnotatedEnpoint.URI)
URI appAnnotatedWSURI;

@Test
void dependencyAnnotatedEndpointShouldWork() throws Exception {
assertWebsocketWorks(dependencyAnnotatedWSURI,
DependencyAnnotatedWS.PREFIX);
}

@Test
void applicationAnnotatedEndpointShouldWork() throws Exception {
assertWebsocketWorks(appAnnotatedWSURI, CustomAnnotatedEnpoint.PREFIX);
}

@Test
void dependencyNotAnnotatedEndpointShouldWork() throws Exception {
assertWebsocketWorks(dependencyNotAnnotatedWSURI,
SimpleEndpoint.PREFIX);
}

void assertWebsocketWorks(URI uri, String messagePrefix) throws Exception {
Client client = new Client();
try (Session session = ContainerProvider.getWebSocketContainer()
.connectToServer(client, uri)) {
Assertions.assertEquals("CONNECT", client.receivedMessage());
Assertions.assertEquals(messagePrefix + "Welcome",
client.receivedMessage());
session.getBasicRemote().sendText("hello world");
Assertions.assertEquals(messagePrefix + "hello world",
client.receivedMessage());
}
}

@ClientEndpoint
public static class Client {
final LinkedBlockingDeque<String> messages = new LinkedBlockingDeque<>();

@OnOpen
public void open(Session session) throws IOException {
messages.add("CONNECT");
}

@OnMessage
void message(String msg) {
messages.add(msg);
}

String receivedMessage() throws InterruptedException {
return messages.poll(12, TimeUnit.SECONDS);
}

}
}
50 changes: 50 additions & 0 deletions integration-tests/custom-websocket-dependency/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?xml version="1.0"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<parent>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-quarkus-integration-tests</artifactId>
<version>1.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

<modelVersion>4.0.0</modelVersion>

<artifactId>custom-websockets</artifactId>
<name>Test dependency with custom websocket endpoints</name>
<packaging>jar</packaging>

<properties>
<maven.deploy.skip>true</maven.deploy.skip>
<maven.javadoc.skip>true</maven.javadoc.skip>
</properties>

<dependencies>
<dependency>
<groupId>jakarta.websocket</groupId>
<artifactId>jakarta.websocket-api</artifactId>
<version>1.1.2</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.jboss.jandex</groupId>
<artifactId>jandex-maven-plugin</artifactId>
<version>1.2.2</version>
<executions>
<execution>
<id>make-index</id>
<goals>
<goal>jandex</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package org.vaadin.sample.websockets;

import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;

@ServerEndpoint(DependencyAnnotatedWS.URI)
public class DependencyAnnotatedWS {

public static final String URI = "/dependency-annotated-websocket";
public static final String PREFIX = ">> Dependency Annotated Endpoint: ";

@OnOpen
public void onOpen(Session session) {
session.getAsyncRemote().sendText(PREFIX + "Welcome");
}

@OnMessage
public void onMessage(String message, Session session) {
session.getAsyncRemote().sendText(PREFIX + message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package org.vaadin.sample.websockets;

import javax.websocket.Endpoint;
import javax.websocket.EndpointConfig;
import javax.websocket.MessageHandler;
import javax.websocket.RemoteEndpoint;
import javax.websocket.Session;

public class SimpleEndpoint extends Endpoint {

public static final String URI = "/dependency-websocket";

public static final String PREFIX = ">> Dependency Simple Endpoint: ";

@Override
public void onOpen(Session session, EndpointConfig config) {
Handler handler = new Handler(session.getAsyncRemote());
session.addMessageHandler(handler);
handler.reply("Welcome");
}

private static class Handler implements MessageHandler.Whole<String> {

private final RemoteEndpoint.Async remote;

public Handler(RemoteEndpoint.Async remote) {
this.remote = remote;
}

@Override
public void onMessage(String message) {
reply(message);
}

private void reply(String message) {
remote.sendText(PREFIX + message);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package org.vaadin.sample.websockets;

import javax.websocket.Endpoint;
import javax.websocket.server.ServerApplicationConfig;
import javax.websocket.server.ServerEndpointConfig;
import java.util.Collections;
import java.util.Set;

public class SimpleEndpointConfig implements ServerApplicationConfig {
@Override
public Set<ServerEndpointConfig> getEndpointConfigs(
Set<Class<? extends Endpoint>> endpointClasses) {
return Set.of(ServerEndpointConfig.Builder
.create(SimpleEndpoint.class, SimpleEndpoint.URI).build());
}

@Override
public Set<Class<?>> getAnnotatedEndpointClasses(Set<Class<?>> scanned) {
return Collections.emptySet();
}
}
5 changes: 5 additions & 0 deletions integration-tests/development/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@
<artifactId>test-addon-with-jandex</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>custom-websockets</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>com.vaadin</groupId>
Expand Down
1 change: 1 addition & 0 deletions integration-tests/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
<!-- Builds testing addons -->
<module>test-addons/addon-with-jandex</module>
<module>test-addons/addon-without-jandex</module>
<module>custom-websocket-dependency</module>
<!-- only validates that code compiles -->
<module>common-test-code</module>

Expand Down
5 changes: 5 additions & 0 deletions integration-tests/production/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@
<artifactId>test-addon-with-jandex</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>custom-websockets</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>com.vaadin</groupId>
Expand Down
21 changes: 19 additions & 2 deletions runtime/src/main/java/com/vaadin/quarkus/EnableWebsockets.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,39 @@
import javax.websocket.server.ServerApplicationConfig;
import javax.websocket.server.ServerEndpointConfig;

import java.util.Collections;
import java.util.Set;

/**
* Only purpose of this class is to automatically enable quarkus WebSocket
* deployment, in order to make Atmosphere JSR365Endpoint work.
*
* Quarkus enables WebSocket deployment only if it finds annotated endpoints
* (@{@link javax.websocket.server.ServerEndpoint}) or implementors of
* {@link ServerApplicationConfig} interface.
*
* Unfortunately, if at least one implementation of
* {@link ServerApplicationConfig} is found, annotated endpoints are not
* deployed automatically.
*
* To circumvent this problem, implementation of
* {@link #getAnnotatedEndpointClasses(Set)} method will return all the provided
* scanned annotated endpoints. Although Javadocs says that the passed set of
* scanned classes contains all the annotated endpoint classes in the JAR or WAR
* file containing the implementation of this interface, Quarkus will instead
* provide all available annotated endpoints found at build time.
*
*/
public class EnableWebsockets implements ServerApplicationConfig {

@Override
public Set<ServerEndpointConfig> getEndpointConfigs(
Set<Class<? extends Endpoint>> endpointClasses) {
return null;
return Collections.emptySet();
}

@Override
public Set<Class<?>> getAnnotatedEndpointClasses(Set<Class<?>> scanned) {
return null;
return scanned;
}
}

0 comments on commit 210ac37

Please sign in to comment.