Adding Support for On Overloads in Java Client (#2568) (#2583)

This commit is contained in:
Mikael Mengistu 2018-07-03 11:44:52 -07:00 committed by GitHub
parent 967db6d8e9
commit b7f666e91b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 234 additions and 38 deletions

View File

@ -1,6 +1,6 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
public interface Action<T> {
void invoke(T param);
}
public interface Action {
void invoke();
}

View File

@ -0,0 +1,6 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
public interface Action1<T1> {
void invoke(T1 param1);
}

View File

@ -0,0 +1,6 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
public interface Action2<T1, T2> {
void invoke(T1 param1, T2 param2);
}

View File

@ -0,0 +1,6 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
public interface Action3<T1, T2, T3> {
void invoke(T1 param1, T2 param2, T3 param3);
}

View File

@ -0,0 +1,6 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
public interface Action4<T1, T2, T3, T4> {
void invoke(T1 param1, T2 param2, T3 param3, T4 param4);
}

View File

@ -0,0 +1,6 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
public interface Action5<T1, T2, T3, T4, T5> {
void invoke(T1 param1, T2 param2, T3 param3, T4 param4, T5 param5);
}

View File

@ -0,0 +1,6 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
public interface ActionBase {
void invoke(Object ... params);
}

View File

@ -1,23 +1,19 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
import com.google.gson.JsonArray;
import java.net.URISyntaxException;
import java.util.Scanner;
public class Chat {
public static void main(String[] args) throws URISyntaxException, InterruptedException {
public static void main(String[] args) throws Exception {
System.out.println("Enter the URL of the SignalR Chat you want to join");
Scanner reader = new Scanner(System.in); // Reading from System.in
String input;
input = reader.nextLine();
HubConnection hubConnection = new HubConnection(input);
hubConnection.On("Send", (message) -> {
String newMessage = ((JsonArray) message).get(0).getAsString();
System.out.println("REGISTERED HANDLER: " + newMessage);
});
hubConnection.on("Send", (message) -> {
System.out.println("REGISTERED HANDLER: " + message);
}, String.class);
//This is a blocking call
hubConnection.start();

View File

@ -1,15 +1,20 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
public class HubConnection {
private String url;
private Transport transport;
private OnReceiveCallBack callback;
private HashMap<String, Action> handlers = new HashMap<>();
private HashMap<String, ActionBase> handlers = new HashMap<>();
private HubProtocol protocol;
private Gson gson = new Gson();
public Boolean connected = false;
@ -24,7 +29,9 @@ public class HubConnection {
// Adding this to avoid getting error messages on pings for now.
for (InvocationMessage message : messages) {
if (message != null && handlers.containsKey(message.target)) {
handlers.get(message.target).invoke(message.arguments[0]);
ArrayList<Object> types = gson.fromJson((JsonArray)message.arguments[0], (new ArrayList<Object>()).getClass());
handlers.get(message.target).invoke(types.toArray());
}
}
};
@ -55,13 +62,48 @@ public class HubConnection {
connected = false;
}
public void send(String method, Object... args) {
public void send(String method, Object... args) throws Exception {
InvocationMessage invocationMessage = new InvocationMessage(method, args);
String message = protocol.writeMessage(invocationMessage);
transport.send(message);
}
public void On(String target, Action callback) {
handlers.put(target, callback);
public void on(String target, Action callback) {
ActionBase ac = args -> callback.invoke();
handlers.put(target, ac);
}
public <T1> void on(String target, Action1<T1> callback, Class<T1> param1) {
ActionBase ac = params -> callback.invoke(param1.cast(params[0]));
handlers.put(target, ac);
}
public <T1, T2> void on(String target, Action2<T1,T2> callback, Class<T1> param1, Class<T2> param2) {
ActionBase action = params -> {
callback.invoke(param1.cast(params[0]), param2.cast(params[1]));
};
handlers.put(target, action);
}
public <T1, T2, T3> void on(String target, Action3<T1,T2, T3> callback, Class<T1> param1, Class<T2> param2, Class<T3> param3) {
ActionBase action = params -> {
callback.invoke(param1.cast(params[0]), param2.cast(params[1]), param3.cast(params[2]));
};
handlers.put(target, action);
}
public <T1, T2, T3, T4> void on(String target, Action4<T1,T2, T3, T4> callback, Class<T1> param1, Class<T2> param2, Class<T3> param3, Class<T4> param4) {
ActionBase action = params -> {
callback.invoke(param1.cast(params[0]), param2.cast(params[1]), param3.cast(params[2]), param4.cast(params[3]));
};
handlers.put(target, action);
}
public <T1, T2, T3, T4,T5> void on(String target, Action5<T1,T2, T3, T4, T5> callback, Class<T1> param1, Class<T2> param2, Class<T3> param3, Class<T4> param4, Class<T5> param5) {
ActionBase action = params -> {
callback.invoke(param1.cast(params[0]), param2.cast(params[1]), param3.cast(params[2]), param4.cast(params[3]),
param5.cast(params[4]));
};
handlers.put(target, action);
}
}

View File

@ -4,5 +4,5 @@
import com.google.gson.JsonObject;
public interface OnReceiveCallBack {
void invoke(String message);
void invoke(String message) throws Exception;
}

View File

@ -3,8 +3,8 @@
public interface Transport {
void start() throws InterruptedException;
void send(String message);
void send(String message) throws Exception;
void setOnReceive(OnReceiveCallBack callback);
void onReceive(String message);
void onReceive(String message) throws Exception;
void stop();
}

View File

@ -36,7 +36,7 @@ public class WebSocketTransport implements Transport {
}
@Override
public void onReceive(String message) {
public void onReceive(String message) throws Exception {
this.onReceiveCallBack.invoke(message);
}
@ -54,7 +54,11 @@ public class WebSocketTransport implements Transport {
@Override
public void onMessage(String message) {
onReceive(message);
try {
onReceive(message);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override

View File

@ -1,10 +1,8 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
import com.google.gson.JsonArray;
import org.junit.Test;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import static org.junit.Assert.*;
@ -21,36 +19,36 @@ public class HubConnectionTest {
assertFalse(hubConnection.connected);
}
// We're using AtomicReference<Double> in the send tests instead of int here because Gson has trouble deserializing to Integer
@Test
public void SendWithNoParamsTriggersOnHandler() throws InterruptedException {
AtomicInteger value = new AtomicInteger(0);
public void SendWithNoParamsTriggersOnHandler() throws Exception {
AtomicReference<Double> value = new AtomicReference<Double>(0.0);
Transport mockTransport = new MockEchoTransport();
HubConnection hubConnection = new HubConnection("http://example.com", mockTransport);
Action callback = (param) -> {
assertEquals(0, value.get());
value.incrementAndGet();
};
hubConnection.On("inc", callback);
hubConnection.on("inc", () ->{
assertEquals(0.0, value.get(), 0);
value.getAndSet(value.get() + 1);
});
hubConnection.start();
hubConnection.send("inc");
// Confirming that our handler was called and that the counter property was incremented.
assertEquals(1, value.get());
assertEquals(1, value.get(), 0);
}
@Test
public void SendWithParamTriggersOnHandler() throws InterruptedException {
public void SendWithParamTriggersOnHandler() throws Exception {
AtomicReference<String> value = new AtomicReference<>();
Transport mockTransport = new MockEchoTransport();
HubConnection hubConnection = new HubConnection("http://example.com", mockTransport);
Action callback = (param) -> {
hubConnection.on("inc", (param) ->{
assertNull(value.get());
value.set(((JsonArray) param).get(0).getAsString());
};
hubConnection.On("inc", callback);
value.set(param);
}, String.class);
hubConnection.start();
hubConnection.send("inc", "Hello World");
@ -59,6 +57,126 @@ public class HubConnectionTest {
assertEquals("Hello World", value.get());
}
@Test
public void SendWithTwoParamsTriggersOnHandler() throws Exception {
AtomicReference<String> value1 = new AtomicReference<>();
AtomicReference<Double> value2 = new AtomicReference<>();
Transport mockTransport = new MockEchoTransport();
HubConnection hubConnection = new HubConnection("http://example.com", mockTransport);
hubConnection.on("inc", (param1, param2) ->{
assertNull(value1.get());
assertNull((value2.get()));
value1.set(param1);
value2.set(param2);
}, String.class, Double.class);
hubConnection.start();
hubConnection.send("inc", "Hello World", 12);
// Confirming that our handler was called and the correct message was passed in.
assertEquals("Hello World", value1.get());
assertEquals(12, value2.get(), 0);
}
@Test
public void SendWithThreeParamsTriggersOnHandler() throws Exception {
AtomicReference<String> value1 = new AtomicReference<>();
AtomicReference<String> value2 = new AtomicReference<>();
AtomicReference<String> value3 = new AtomicReference<>();
Transport mockTransport = new MockEchoTransport();
HubConnection hubConnection = new HubConnection("http://example.com", mockTransport);
hubConnection.on("inc", (param1, param2, param3) ->{
assertNull(value1.get());
assertNull(value2.get());
assertNull(value3.get());
value1.set(param1);
value2.set(param2);
value3.set(param3);
}, String.class, String.class, String.class);
hubConnection.start();
hubConnection.send("inc", "A", "B", "C");
// Confirming that our handler was called and the correct message was passed in.
assertEquals("A", value1.get());
assertEquals("B", value2.get());
assertEquals("C", value3.get());
}
@Test
public void SendWithFourParamsTriggersOnHandler() throws Exception {
AtomicReference<String> value1 = new AtomicReference<>();
AtomicReference<String> value2 = new AtomicReference<>();
AtomicReference<String> value3 = new AtomicReference<>();
AtomicReference<String> value4 = new AtomicReference<>();
Transport mockTransport = new MockEchoTransport();
HubConnection hubConnection = new HubConnection("http://example.com", mockTransport);
hubConnection.on("inc", (param1, param2, param3, param4) ->{
assertNull(value1.get());
assertNull(value2.get());
assertNull(value3.get());
assertNull(value4.get());
value1.set(param1);
value2.set(param2);
value3.set(param3);
value4.set(param4);
}, String.class, String.class, String.class, String.class);
hubConnection.start();
hubConnection.send("inc", "A", "B", "C", "D");
// Confirming that our handler was called and the correct message was passed in.
assertEquals("A", value1.get());
assertEquals("B", value2.get());
assertEquals("C", value3.get());
assertEquals("D", value4.get());
}
@Test
public void SendWithFiveParamsTriggersOnHandler() throws Exception {
AtomicReference<String> value1 = new AtomicReference<>();
AtomicReference<String> value2 = new AtomicReference<>();
AtomicReference<String> value3 = new AtomicReference<>();
AtomicReference<Boolean> value4 = new AtomicReference<>();
AtomicReference<Double> value5 = new AtomicReference<>();
Transport mockTransport = new MockEchoTransport();
HubConnection hubConnection = new HubConnection("http://example.com", mockTransport);
hubConnection.on("inc", (param1, param2, param3, param4, param5) ->{
assertNull(value1.get());
assertNull(value2.get());
assertNull(value3.get());
assertNull(value4.get());
assertNull(value5.get());
value1.set(param1);
value2.set(param2);
value3.set(param3);
value4.set(param4);
value5.set(param5);
}, String.class, String.class, String.class, Boolean.class, Double.class);
hubConnection.start();
hubConnection.send("inc", "A", "B", "C", true, 12.0);
// Confirming that our handler was called and the correct message was passed in.
assertEquals("A", value1.get());
assertEquals("B", value2.get());
assertEquals("C", value3.get());
assertTrue(value4.get());
assertEquals(12, value5.get(), 0);
}
private class MockEchoTransport implements Transport {
private OnReceiveCallBack onReceiveCallBack;
@ -66,7 +184,7 @@ public class HubConnectionTest {
public void start() {}
@Override
public void send(String message) {
public void send(String message) throws Exception {
this.onReceive(message);
}
@ -76,7 +194,7 @@ public class HubConnectionTest {
}
@Override
public void onReceive(String message) {
public void onReceive(String message) throws Exception {
this.onReceiveCallBack.invoke(message);
}