diff --git a/clients/java/signalr/src/main/java/Action.java b/clients/java/signalr/src/main/java/Action.java index 79c4da61a2..8d41276eb6 100644 --- a/clients/java/signalr/src/main/java/Action.java +++ b/clients/java/signalr/src/main/java/Action.java @@ -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 { - void invoke(T param); -} \ No newline at end of file +public interface Action { + void invoke(); +} diff --git a/clients/java/signalr/src/main/java/Action1.java b/clients/java/signalr/src/main/java/Action1.java new file mode 100644 index 0000000000..ae4c4d7cbb --- /dev/null +++ b/clients/java/signalr/src/main/java/Action1.java @@ -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 { + void invoke(T1 param1); +} diff --git a/clients/java/signalr/src/main/java/Action2.java b/clients/java/signalr/src/main/java/Action2.java new file mode 100644 index 0000000000..41ab3b123f --- /dev/null +++ b/clients/java/signalr/src/main/java/Action2.java @@ -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 { + void invoke(T1 param1, T2 param2); +} diff --git a/clients/java/signalr/src/main/java/Action3.java b/clients/java/signalr/src/main/java/Action3.java new file mode 100644 index 0000000000..b79e6449df --- /dev/null +++ b/clients/java/signalr/src/main/java/Action3.java @@ -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 { + void invoke(T1 param1, T2 param2, T3 param3); +} diff --git a/clients/java/signalr/src/main/java/Action4.java b/clients/java/signalr/src/main/java/Action4.java new file mode 100644 index 0000000000..34665d8fd6 --- /dev/null +++ b/clients/java/signalr/src/main/java/Action4.java @@ -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 { + void invoke(T1 param1, T2 param2, T3 param3, T4 param4); +} diff --git a/clients/java/signalr/src/main/java/Action5.java b/clients/java/signalr/src/main/java/Action5.java new file mode 100644 index 0000000000..446aa52132 --- /dev/null +++ b/clients/java/signalr/src/main/java/Action5.java @@ -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 { + void invoke(T1 param1, T2 param2, T3 param3, T4 param4, T5 param5); +} diff --git a/clients/java/signalr/src/main/java/ActionBase.java b/clients/java/signalr/src/main/java/ActionBase.java new file mode 100644 index 0000000000..09b1bc7cfb --- /dev/null +++ b/clients/java/signalr/src/main/java/ActionBase.java @@ -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); +} diff --git a/clients/java/signalr/src/main/java/Chat.java b/clients/java/signalr/src/main/java/Chat.java index a64b107c94..a7ce9f9738 100644 --- a/clients/java/signalr/src/main/java/Chat.java +++ b/clients/java/signalr/src/main/java/Chat.java @@ -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(); diff --git a/clients/java/signalr/src/main/java/HubConnection.java b/clients/java/signalr/src/main/java/HubConnection.java index 68db2bf090..b33df34019 100644 --- a/clients/java/signalr/src/main/java/HubConnection.java +++ b/clients/java/signalr/src/main/java/HubConnection.java @@ -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 handlers = new HashMap<>(); + private HashMap 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 types = gson.fromJson((JsonArray)message.arguments[0], (new ArrayList()).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 void on(String target, Action1 callback, Class param1) { + ActionBase ac = params -> callback.invoke(param1.cast(params[0])); + handlers.put(target, ac); + } + + public void on(String target, Action2 callback, Class param1, Class param2) { + ActionBase action = params -> { + callback.invoke(param1.cast(params[0]), param2.cast(params[1])); + }; + handlers.put(target, action); + } + + public void on(String target, Action3 callback, Class param1, Class param2, Class param3) { + ActionBase action = params -> { + callback.invoke(param1.cast(params[0]), param2.cast(params[1]), param3.cast(params[2])); + }; + handlers.put(target, action); + } + + public void on(String target, Action4 callback, Class param1, Class param2, Class param3, Class 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 void on(String target, Action5 callback, Class param1, Class param2, Class param3, Class param4, Class 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); } } \ No newline at end of file diff --git a/clients/java/signalr/src/main/java/OnReceiveCallBack.java b/clients/java/signalr/src/main/java/OnReceiveCallBack.java index e461b47c1a..6d971d1955 100644 --- a/clients/java/signalr/src/main/java/OnReceiveCallBack.java +++ b/clients/java/signalr/src/main/java/OnReceiveCallBack.java @@ -4,5 +4,5 @@ import com.google.gson.JsonObject; public interface OnReceiveCallBack { - void invoke(String message); + void invoke(String message) throws Exception; } diff --git a/clients/java/signalr/src/main/java/Transport.java b/clients/java/signalr/src/main/java/Transport.java index 819460b9d1..240675dfe5 100644 --- a/clients/java/signalr/src/main/java/Transport.java +++ b/clients/java/signalr/src/main/java/Transport.java @@ -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(); } diff --git a/clients/java/signalr/src/main/java/WebSocketTransport.java b/clients/java/signalr/src/main/java/WebSocketTransport.java index 1fa6a68b70..f1218785c2 100644 --- a/clients/java/signalr/src/main/java/WebSocketTransport.java +++ b/clients/java/signalr/src/main/java/WebSocketTransport.java @@ -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 diff --git a/clients/java/signalr/src/test/java/HubConnectionTest.java b/clients/java/signalr/src/test/java/HubConnectionTest.java index ec55e3f875..e50ab7a647 100644 --- a/clients/java/signalr/src/test/java/HubConnectionTest.java +++ b/clients/java/signalr/src/test/java/HubConnectionTest.java @@ -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 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 value = new AtomicReference(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 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 value1 = new AtomicReference<>(); + AtomicReference 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 value1 = new AtomicReference<>(); + AtomicReference value2 = new AtomicReference<>(); + AtomicReference 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 value1 = new AtomicReference<>(); + AtomicReference value2 = new AtomicReference<>(); + AtomicReference value3 = new AtomicReference<>(); + AtomicReference 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 value1 = new AtomicReference<>(); + AtomicReference value2 = new AtomicReference<>(); + AtomicReference value3 = new AtomicReference<>(); + AtomicReference value4 = new AtomicReference<>(); + AtomicReference 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); }