Skip to content
This repository was archived by the owner on Mar 3, 2026. It is now read-only.

Commit 753323c

Browse files
committed
kotlin: Mvc websocket fails to detect generic type fix jooby-project#951
1 parent 25501b1 commit 753323c

File tree

2 files changed

+127
-8
lines changed

2 files changed

+127
-8
lines changed

jooby/src/main/java/org/jooby/internal/mvc/MvcWebSocket.java

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@
213213
import java.lang.reflect.ParameterizedType;
214214
import java.lang.reflect.Type;
215215
import java.util.Arrays;
216+
import java.util.function.Predicate;
216217

217218
@SuppressWarnings({"rawtypes", "unchecked"})
218219
public class MvcWebSocket implements WebSocket.Handler<Mutant> {
@@ -223,7 +224,7 @@ public class MvcWebSocket implements WebSocket.Handler<Mutant> {
223224

224225
MvcWebSocket(final WebSocket ws, final Class handler) {
225226
Injector injector = ws.require(Injector.class)
226-
.createChildInjector(binder -> binder.bind(WebSocket.class).toInstance(ws));
227+
.createChildInjector(binder -> binder.bind(WebSocket.class).toInstance(ws));
227228
this.handler = injector.getInstance(handler);
228229
this.messageType = TypeLiteral.get(messageType(handler));
229230
}
@@ -278,13 +279,17 @@ private boolean isError() {
278279

279280
static Type messageType(final Class handler) {
280281
return Arrays.asList(handler.getGenericInterfaces())
281-
.stream()
282-
.filter(it -> TypeLiteral.get(it).getRawType().isAssignableFrom(WebSocket.OnMessage.class))
283-
.findFirst()
284-
.filter(ParameterizedType.class::isInstance)
285-
.map(it -> ((ParameterizedType) it).getActualTypeArguments()[0])
286-
.orElseThrow(() -> new IllegalArgumentException(
287-
"Can't extract message type from: " + handler.getName()));
282+
.stream()
283+
.filter(rawTypeIs(WebSocket.Handler.class).or(rawTypeIs(WebSocket.OnMessage.class)))
284+
.findFirst()
285+
.filter(ParameterizedType.class::isInstance)
286+
.map(it -> ((ParameterizedType) it).getActualTypeArguments()[0])
287+
.orElseThrow(() -> new IllegalArgumentException(
288+
"Can't extract message type from: " + handler.getName()));
289+
}
290+
291+
private static Predicate<Type> rawTypeIs(Class<?> type) {
292+
return it -> TypeLiteral.get(it).getRawType().isAssignableFrom(type);
288293
}
289294

290295
}
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
package org.jooby.issues;
2+
3+
import com.ning.http.client.AsyncHttpClient;
4+
import com.ning.http.client.AsyncHttpClientConfig;
5+
import com.ning.http.client.ws.WebSocket;
6+
import com.ning.http.client.ws.WebSocketTextListener;
7+
import com.ning.http.client.ws.WebSocketUpgradeHandler;
8+
import org.jooby.Request;
9+
import org.jooby.json.Jackson;
10+
import org.jooby.test.ServerFeature;
11+
import org.junit.After;
12+
import static org.junit.Assert.assertEquals;
13+
import org.junit.Before;
14+
import org.junit.Test;
15+
16+
import javax.inject.Inject;
17+
import java.util.Arrays;
18+
import java.util.LinkedList;
19+
import java.util.concurrent.CountDownLatch;
20+
import java.util.concurrent.TimeUnit;
21+
22+
public class Issue951 extends ServerFeature {
23+
24+
public static class User {
25+
public String name;
26+
27+
@Override
28+
public String toString() {
29+
return name;
30+
}
31+
}
32+
33+
public static class MySocket implements org.jooby.WebSocket.Handler<User> {
34+
35+
private org.jooby.WebSocket ws;
36+
37+
@Inject
38+
public MySocket(final org.jooby.WebSocket ws) {
39+
this.ws = ws;
40+
}
41+
42+
@Override
43+
public void onMessage(final User message) throws Exception {
44+
ws.send("=" + message);
45+
}
46+
47+
@Override public void onOpen(Request req, org.jooby.WebSocket ws) throws Exception {
48+
49+
}
50+
51+
@Override public void onClose(org.jooby.WebSocket.CloseStatus status) throws Exception {
52+
53+
}
54+
55+
@Override public void onError(Throwable err) {
56+
57+
}
58+
}
59+
60+
{
61+
use(new Jackson());
62+
63+
ws("/951", MySocket.class)
64+
.consumes("json");
65+
}
66+
67+
private AsyncHttpClient client;
68+
69+
@Before
70+
public void before() {
71+
client = new AsyncHttpClient(new AsyncHttpClientConfig.Builder().build());
72+
}
73+
74+
@After
75+
public void after() {
76+
client.close();
77+
}
78+
79+
@Test
80+
public void genericTypeOnHandlerObject() throws Exception {
81+
LinkedList<String> messages = new LinkedList<>();
82+
83+
CountDownLatch latch = new CountDownLatch(1);
84+
85+
client.prepareGet(ws("951").toString())
86+
.execute(new WebSocketUpgradeHandler.Builder().addWebSocketListener(
87+
new WebSocketTextListener() {
88+
89+
@Override
90+
public void onMessage(final String message) {
91+
messages.add(message);
92+
latch.countDown();
93+
}
94+
95+
@Override
96+
public void onOpen(final WebSocket websocket) {
97+
websocket.sendMessage("{\"name\":\"pablo marmol\"}");
98+
}
99+
100+
@Override
101+
public void onClose(final WebSocket websocket) {
102+
}
103+
104+
@Override
105+
public void onError(final Throwable t) {
106+
}
107+
}).build())
108+
.get();
109+
if (latch.await(1L, TimeUnit.SECONDS)) {
110+
assertEquals(Arrays.asList("=pablo marmol"), messages);
111+
}
112+
}
113+
114+
}

0 commit comments

Comments
 (0)