From 7b0c175b80177c2424449b48081cae4296f6f023 Mon Sep 17 00:00:00 2001 From: Giovanni Lovato Date: Thu, 28 Jun 2018 08:57:05 +0200 Subject: [PATCH] Add RPC support for composite components (#4298) * Add RPC support for composite components * Support composite of composite * Split method search in hierarchy --- ...PublishedServerEventHandlerRpcHandler.java | 27 +++++++++++---- ...ishedServerEventHandlerRpcHandlerTest.java | 33 +++++++++++++++++-- 2 files changed, 52 insertions(+), 8 deletions(-) diff --git a/flow-server/src/main/java/com/vaadin/flow/server/communication/rpc/PublishedServerEventHandlerRpcHandler.java b/flow-server/src/main/java/com/vaadin/flow/server/communication/rpc/PublishedServerEventHandlerRpcHandler.java index c588df0cfdd..8010e0aba26 100644 --- a/flow-server/src/main/java/com/vaadin/flow/server/communication/rpc/PublishedServerEventHandlerRpcHandler.java +++ b/flow-server/src/main/java/com/vaadin/flow/server/communication/rpc/PublishedServerEventHandlerRpcHandler.java @@ -30,6 +30,7 @@ import com.vaadin.flow.component.ClientCallable; import com.vaadin.flow.component.Component; +import com.vaadin.flow.component.Composite; import com.vaadin.flow.component.polymertemplate.EventHandler; import com.vaadin.flow.component.polymertemplate.PolymerTemplate; import com.vaadin.flow.dom.DisabledUpdateMode; @@ -123,6 +124,23 @@ public Optional handleNode(StateNode node, static void invokeMethod(Component instance, Class clazz, String methodName, JsonArray args) { assert instance != null; + Optional method = findMethod(instance, clazz, methodName); + if (method.isPresent()) { + invokeMethod(instance, method.get(), args); + } else if (instance instanceof Composite) { + Component compositeContent = ((Composite) instance).getContent(); + invokeMethod(compositeContent, compositeContent.getClass(), + methodName, args); + } else { + String msg = String.format("Neither class '%s' " + + "nor its super classes declare event handler method '%s'", + instance.getClass().getName(), methodName); + throw new IllegalStateException(msg); + } + } + + private static Optional findMethod(Component instance, + Class clazz, String methodName) { List methods = Stream.of(clazz.getDeclaredMethods()) .filter(method -> methodName.equals(method.getName())) .filter(method -> method.isAnnotationPresent(EventHandler.class) @@ -134,14 +152,11 @@ static void invokeMethod(Component instance, Class clazz, instance.getClass().getName(), methodName); throw new IllegalStateException(msg); } else if (methods.size() == 1) { - invokeMethod(instance, methods.get(0), args); + return Optional.of(methods.get(0)); } else if (!Component.class.equals(clazz)) { - invokeMethod(instance, clazz.getSuperclass(), methodName, args); + return findMethod(instance, clazz.getSuperclass(), methodName); } else { - String msg = String.format("Neither class '%s' " - + "nor its super classes declare event handler method '%s'", - instance.getClass().getName(), methodName); - throw new IllegalStateException(msg); + return Optional.empty(); } } diff --git a/flow-server/src/test/java/com/vaadin/flow/server/communication/rpc/PublishedServerEventHandlerRpcHandlerTest.java b/flow-server/src/test/java/com/vaadin/flow/server/communication/rpc/PublishedServerEventHandlerRpcHandlerTest.java index b4af7c85b5c..85b58ba2208 100644 --- a/flow-server/src/test/java/com/vaadin/flow/server/communication/rpc/PublishedServerEventHandlerRpcHandlerTest.java +++ b/flow-server/src/test/java/com/vaadin/flow/server/communication/rpc/PublishedServerEventHandlerRpcHandlerTest.java @@ -15,6 +15,7 @@ */ package com.vaadin.flow.server.communication.rpc; +import net.jcip.annotations.NotThreadSafe; import org.jsoup.nodes.Element; import org.junit.After; import org.junit.Assert; @@ -24,6 +25,7 @@ import com.vaadin.flow.component.ClientCallable; import com.vaadin.flow.component.Component; +import com.vaadin.flow.component.Composite; import com.vaadin.flow.component.EventData; import com.vaadin.flow.component.Tag; import com.vaadin.flow.component.UI; @@ -40,7 +42,6 @@ import elemental.json.JsonArray; import elemental.json.JsonObject; import elemental.json.JsonValue; -import net.jcip.annotations.NotThreadSafe; @NotThreadSafe public class PublishedServerEventHandlerRpcHandlerTest { @@ -53,7 +54,7 @@ public static class ComponentWithMethod private boolean isInvoked; - ComponentWithMethod() { + public ComponentWithMethod() { super((clazz, tag, service) -> new TemplateData("", new Element("a"))); } @@ -189,6 +190,14 @@ public void operation() { } } + public static class CompositeOfComponentWithMethod + extends Composite { + } + + public static class CompositeOfComposite + extends Composite { + } + @Before public void setUp() { Assert.assertNull(System.getSecurityManager()); @@ -217,6 +226,26 @@ public void methodIsInvoked() { Assert.assertTrue(component.isInvoked); } + @Test + public void methodIsInvokedOnCompositeContent() { + CompositeOfComponentWithMethod composite = new CompositeOfComponentWithMethod(); + ComponentWithMethod component = composite.getContent(); + PublishedServerEventHandlerRpcHandler.invokeMethod(composite, + composite.getClass(), "method", Json.createArray()); + + Assert.assertTrue(component.isInvoked); + } + + @Test + public void methodIsInvokectOnCompositeOfComposite() { + CompositeOfComposite composite = new CompositeOfComposite(); + ComponentWithMethod component = composite.getContent().getContent(); + PublishedServerEventHandlerRpcHandler.invokeMethod(composite, + composite.getClass(), "method", Json.createArray()); + + Assert.assertTrue(component.isInvoked); + } + @Test public void methodWithDecoderParameters_convertableValues_methodIsInvoked() { JsonArray params = Json.createArray();