Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: make sure annotated endpoints works along Vaadin PUSH (CP: 1.1) #90

Merged
merged 1 commit into from
Dec 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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,23 @@
package org.vaadin.sample.websockets;

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

@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;
}
}