Skip to content

Commit

Permalink
WebSockets Next: support arrays as valid return types of callbacks
Browse files Browse the repository at this point in the history
- for binary messages a custom codec is always needed
  • Loading branch information
mkouba committed Nov 14, 2024
1 parent 20dc22a commit d90b5f9
Show file tree
Hide file tree
Showing 4 changed files with 194 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -1594,10 +1594,10 @@ static boolean hasBlockingSignature(MethodInfo method) {
if (KotlinUtils.isKotlinSuspendMethod(method)) {
return false;
}

switch (method.returnType().kind()) {
case VOID:
case CLASS:
case ARRAY:
return true;
case PARAMETERIZED_TYPE:
// Uni, Multi -> non-blocking
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package io.quarkus.websockets.next.test.codec;

import static org.junit.jupiter.api.Assertions.assertEquals;

import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Type;
import java.net.URI;

import jakarta.inject.Inject;
import jakarta.inject.Singleton;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.test.QuarkusUnitTest;
import io.quarkus.test.common.http.TestHTTPResource;
import io.quarkus.websockets.next.BinaryMessageCodec;
import io.quarkus.websockets.next.OnBinaryMessage;
import io.quarkus.websockets.next.WebSocket;
import io.quarkus.websockets.next.test.utils.WSClient;
import io.vertx.core.Vertx;
import io.vertx.core.buffer.Buffer;

public class ArrayBinaryCodecTest {

@RegisterExtension
public static final QuarkusUnitTest test = new QuarkusUnitTest()
.withApplicationRoot(root -> {
root.addClasses(Item.class, Endpoint.class, WSClient.class, ItemArrayBinaryCodec.class);
});

@Inject
Vertx vertx;

@TestHTTPResource("end")
URI testUri;

@Test
public void testCodec() {
try (WSClient client = new WSClient(vertx)) {
client.connect(testUri);
client.sendAndAwait(Buffer.buffer("Foo"));
client.waitForMessages(1);
assertEquals("Foo", client.getMessages().get(0).toString());
}
}

@Singleton
public static class ItemArrayBinaryCodec implements BinaryMessageCodec<Item[]> {

@Override
public boolean supports(Type type) {
return (type instanceof GenericArrayType) || (type instanceof Class<?> && ((Class<?>) type).isArray());
}

@Override
public Buffer encode(Item[] value) {
return Buffer.buffer(value[0].getName());
}

@Override
public Item[] decode(Type type, Buffer value) {
throw new UnsupportedOperationException();
}

}

@WebSocket(path = "/end")
public static class Endpoint {

@OnBinaryMessage
Item[] process(String name) {
Item item = new Item();
item.setName(name);
item.setCount(1);
return new Item[] { item };
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package io.quarkus.websockets.next.test.codec;

import static org.junit.jupiter.api.Assertions.assertEquals;

import java.net.URI;

import jakarta.inject.Inject;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.test.QuarkusUnitTest;
import io.quarkus.test.common.http.TestHTTPResource;
import io.quarkus.websockets.next.OnOpen;
import io.quarkus.websockets.next.WebSocket;
import io.quarkus.websockets.next.test.utils.WSClient;
import io.vertx.core.Vertx;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;

public class ArrayTextCodecTest {

@RegisterExtension
public static final QuarkusUnitTest test = new QuarkusUnitTest()
.withApplicationRoot(root -> {
root.addClasses(Item.class, Endpont.class, WSClient.class);
});

@Inject
Vertx vertx;

@TestHTTPResource("end")
URI testUri;

@Test
public void testCodec() throws Exception {
try (WSClient client = new WSClient(vertx)) {
client.connect(testUri);
client.waitForMessages(1);
assertEquals(new JsonArray().add(new JsonObject().put("name", "Foo").put("count", 1)).toString(),
client.getMessages().get(0).toString());
}
}

@WebSocket(path = "/end")
public static class Endpont {

// The default JsonTextMessageCodec is used
@OnOpen
Item[] open() {
Item item = new Item();
item.setName("Foo");
item.setCount(1);
return new Item[] { item };
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package io.quarkus.websockets.next.test.codec;

import static org.junit.jupiter.api.Assertions.assertEquals;

import java.net.URI;

import jakarta.inject.Inject;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.test.QuarkusUnitTest;
import io.quarkus.test.common.http.TestHTTPResource;
import io.quarkus.websockets.next.OnBinaryMessage;
import io.quarkus.websockets.next.WebSocket;
import io.quarkus.websockets.next.test.utils.WSClient;
import io.vertx.core.Vertx;
import io.vertx.core.buffer.Buffer;

public class ByteArrayBinaryMessageTest {

@RegisterExtension
public static final QuarkusUnitTest test = new QuarkusUnitTest()
.withApplicationRoot(root -> {
root.addClasses(Endpont.class, WSClient.class);
});

@Inject
Vertx vertx;

@TestHTTPResource("end")
URI testUri;

@Test
public void testCodec() throws Exception {
try (WSClient client = new WSClient(vertx)) {
client.connect(testUri);
client.send(Buffer.buffer("43"));
client.waitForMessages(1);
assertEquals("43", client.getMessages().get(0).toString());
}
}

@WebSocket(path = "/end")
public static class Endpont {

// This is an equivalent to Sender#sendBinary(byte[])
// byte[] is encoded with Buffer#buffer(byte[]), codec is not needed
@OnBinaryMessage
byte[] echo(Buffer message) {
return message.getBytes();
}

}
}

0 comments on commit d90b5f9

Please sign in to comment.