From 2d4fb0af6fd2ef2e3a059a2a15a56484d8800d35 Mon Sep 17 00:00:00 2001 From: Mikael Mengistu Date: Mon, 9 Jul 2018 15:27:49 -0500 Subject: [PATCH] Add support for registering multiple On handlers (#2599) --- .../signalr/src/main/java/CallbackMap.java | 28 +++++++++++++ .../signalr/src/main/java/HubConnection.java | 14 ++++--- .../src/test/java/HubConnectionTest.java | 42 ++++++++++++++++++- 3 files changed, 78 insertions(+), 6 deletions(-) create mode 100644 clients/java/signalr/src/main/java/CallbackMap.java diff --git a/clients/java/signalr/src/main/java/CallbackMap.java b/clients/java/signalr/src/main/java/CallbackMap.java new file mode 100644 index 0000000000..b0182478b0 --- /dev/null +++ b/clients/java/signalr/src/main/java/CallbackMap.java @@ -0,0 +1,28 @@ +// 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 java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; + +public class CallbackMap { + private ConcurrentHashMap> handlers = new ConcurrentHashMap<>(); + + public void put(String target, ActionBase action) { + handlers.computeIfPresent(target, (methodName, handlerList) -> { + handlerList.add(action); + return handlerList; + }); + handlers.computeIfAbsent(target, (ac) -> new ArrayList<>(Arrays.asList(action))); + } + + public Boolean containsKey(String key){ + return handlers.containsKey(key); + } + + public List get(String key){ + return handlers.get(key); + } +} + diff --git a/clients/java/signalr/src/main/java/HubConnection.java b/clients/java/signalr/src/main/java/HubConnection.java index b33df34019..28a65e45dc 100644 --- a/clients/java/signalr/src/main/java/HubConnection.java +++ b/clients/java/signalr/src/main/java/HubConnection.java @@ -6,13 +6,13 @@ import com.google.gson.JsonArray; import java.net.URISyntaxException; import java.util.ArrayList; -import java.util.HashMap; +import java.util.List; public class HubConnection { private String url; private Transport transport; private OnReceiveCallBack callback; - private HashMap handlers = new HashMap<>(); + private CallbackMap handlers = new CallbackMap(); private HubProtocol protocol; private Gson gson = new Gson(); @@ -29,9 +29,13 @@ 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)) { - ArrayList types = gson.fromJson((JsonArray)message.arguments[0], (new ArrayList()).getClass()); - - handlers.get(message.target).invoke(types.toArray()); + ArrayList args = gson.fromJson((JsonArray)message.arguments[0], (new ArrayList()).getClass()); + List actions = handlers.get(message.target); + if (actions != null) { + for (ActionBase action: actions) { + action.invoke(args.toArray()); + } + } } } }; diff --git a/clients/java/signalr/src/test/java/HubConnectionTest.java b/clients/java/signalr/src/test/java/HubConnectionTest.java index e50ab7a647..ce502183ea 100644 --- a/clients/java/signalr/src/test/java/HubConnectionTest.java +++ b/clients/java/signalr/src/test/java/HubConnectionTest.java @@ -19,6 +19,46 @@ public class HubConnectionTest { assertFalse(hubConnection.connected); } + @Test + public void RegisteringMultipleHandlersAndBothGetTriggered() throws Exception { + + AtomicReference value = new AtomicReference<>(0.0); + Transport mockTransport = new MockEchoTransport(); + HubConnection hubConnection = new HubConnection("http://example.com", mockTransport); + Action action = () -> value.getAndUpdate((val) -> val + 1); + + hubConnection.on("inc", action); + hubConnection.on("inc", action); + + assertEquals(0.0, value.get(), 0); + + hubConnection.start(); + hubConnection.send("inc"); + + // Confirming that our handler was called and that the counter property was incremented. + assertEquals(2, value.get(), 0); + } + + @Test + public void RegisteringMultipleHandlersThatTakeParamsAndBothGetTriggered() throws Exception { + AtomicReference value = new AtomicReference<>(0.0); + Transport mockTransport = new MockEchoTransport(); + HubConnection hubConnection = new HubConnection("http://example.com", mockTransport); + + Action1 action = (number) -> value.getAndUpdate((val) -> val + number); + + hubConnection.on("add", action, Double.class); + hubConnection.on("add", action, Double.class); + + assertEquals(0, value.get(), 0); + hubConnection.start(); + hubConnection.send("add", 12); + + // Confirming that our handler was called and the correct message was passed in. + assertEquals(24, value.get(), 0); + } + + // We're using AtomicReference in the send tests instead of int here because Gson has trouble deserializing to Integer @Test public void SendWithNoParamsTriggersOnHandler() throws Exception { @@ -29,7 +69,7 @@ public class HubConnectionTest { hubConnection.on("inc", () ->{ assertEquals(0.0, value.get(), 0); - value.getAndSet(value.get() + 1); + value.getAndUpdate((val) -> val + 1); }); hubConnection.start();