aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArtur Signell <artur@vaadin.com>2015-10-22 15:13:27 +0300
committerVaadin Code Review <review@vaadin.com>2016-03-05 11:20:23 +0000
commit39640d188b0c7b9964d5df34f97a83839f2b3732 (patch)
treeb18f34910bd9d16aadb7fb003c7be5d37b707525
parent16f9434bee7a8eebaf580d82db25a47e8b24bbdd (diff)
downloadvaadin-framework-39640d188b0c7b9964d5df34f97a83839f2b3732.tar.gz
vaadin-framework-39640d188b0c7b9964d5df34f97a83839f2b3732.zip
Make it possible to intercept RPC calls without copy/paste
Change-Id: I50c2e4a95b492a42c4291e8dcbede3de87f1be6f
-rw-r--r--WebContent/WEB-INF/web.xml14
-rw-r--r--server/src/com/vaadin/server/communication/ServerRpcHandler.java98
-rw-r--r--server/src/com/vaadin/server/communication/UidlRequestHandler.java13
-rw-r--r--uitest/src/com/vaadin/tests/rpclogger/LoggingServerRpcHandler.java40
-rw-r--r--uitest/src/com/vaadin/tests/rpclogger/LoggingUidlRequestHandler.java28
-rw-r--r--uitest/src/com/vaadin/tests/rpclogger/RPCLoggerService.java41
-rw-r--r--uitest/src/com/vaadin/tests/rpclogger/RPCLoggerServlet.java34
-rw-r--r--uitest/src/com/vaadin/tests/rpclogger/RPCLoggerUI.java177
8 files changed, 412 insertions, 33 deletions
diff --git a/WebContent/WEB-INF/web.xml b/WebContent/WEB-INF/web.xml
index 1879175109..0def4001b8 100644
--- a/WebContent/WEB-INF/web.xml
+++ b/WebContent/WEB-INF/web.xml
@@ -109,6 +109,15 @@
</init-param>
<async-supported>true</async-supported>
</servlet>
+ <servlet>
+ <servlet-name>RPCLogger</servlet-name>
+ <servlet-class>com.vaadin.tests.rpclogger.RPCLoggerServlet</servlet-class>
+ <init-param>
+ <param-name>ui</param-name>
+ <param-value>com.vaadin.tests.rpclogger.RPCLoggerUI</param-value>
+ </init-param>
+ <async-supported>true</async-supported>
+ </servlet>
<servlet>
<!-- This servlet is a separate instance for the sole purpose of
@@ -203,6 +212,11 @@
</servlet-mapping>
<servlet-mapping>
+ <servlet-name>RPCLogger</servlet-name>
+ <url-pattern>/rpclogger/*</url-pattern>
+ </servlet-mapping>
+
+ <servlet-mapping>
<servlet-name>VaadinStaticFiles</servlet-name>
<url-pattern>/VAADIN/*</url-pattern>
</servlet-mapping>
diff --git a/server/src/com/vaadin/server/communication/ServerRpcHandler.java b/server/src/com/vaadin/server/communication/ServerRpcHandler.java
index 593b1f544f..3503a2d8b1 100644
--- a/server/src/com/vaadin/server/communication/ServerRpcHandler.java
+++ b/server/src/com/vaadin/server/communication/ServerRpcHandler.java
@@ -316,7 +316,7 @@ public class ServerRpcHandler implements Serializable {
* 6 semantics for components and add-ons that do not use Vaadin 7 RPC
* directly.
*
- * @param uI
+ * @param ui
* the UI receiving the invocations data
* @param lastSyncIdSeenByClient
* the most recent sync id the client has seen at the time the
@@ -324,20 +324,21 @@ public class ServerRpcHandler implements Serializable {
* @param invocationsData
* JSON containing all information needed to execute all
* requested RPC calls.
+ * @since
*/
- private void handleInvocations(UI uI, int lastSyncIdSeenByClient,
+ protected void handleInvocations(UI ui, int lastSyncIdSeenByClient,
JsonArray invocationsData) {
// TODO PUSH Refactor so that this is not needed
- LegacyCommunicationManager manager = uI.getSession()
+ LegacyCommunicationManager manager = ui.getSession()
.getCommunicationManager();
try {
- ConnectorTracker connectorTracker = uI.getConnectorTracker();
+ ConnectorTracker connectorTracker = ui.getConnectorTracker();
Set<Connector> enabledConnectors = new HashSet<Connector>();
List<MethodInvocation> invocations = parseInvocations(
- uI.getConnectorTracker(), invocationsData,
+ ui.getConnectorTracker(), invocationsData,
lastSyncIdSeenByClient);
for (MethodInvocation invocation : invocations) {
final ClientConnector connector = connectorTracker
@@ -404,35 +405,11 @@ public class ServerRpcHandler implements Serializable {
}
if (invocation instanceof ServerRpcMethodInvocation) {
- try {
- ServerRpcManager.applyInvocation(connector,
- (ServerRpcMethodInvocation) invocation);
- } catch (RpcInvocationException e) {
- manager.handleConnectorRelatedException(connector, e);
- }
+ handleInvocation(ui, connector,
+ (ServerRpcMethodInvocation) invocation);
} else {
-
- // All code below is for legacy variable changes
LegacyChangeVariablesInvocation legacyInvocation = (LegacyChangeVariablesInvocation) invocation;
- Map<String, Object> changes = legacyInvocation
- .getVariableChanges();
- try {
- if (connector instanceof VariableOwner) {
- // The source parameter is never used anywhere
- changeVariables(null, (VariableOwner) connector,
- changes);
- } else {
- throw new IllegalStateException(
- "Received legacy variable change for "
- + connector.getClass().getName()
- + " ("
- + connector.getConnectorId()
- + ") which is not a VariableOwner. The client-side connector sent these legacy varaibles: "
- + changes.keySet());
- }
- } catch (Exception e) {
- manager.handleConnectorRelatedException(connector, e);
- }
+ handleInvocation(ui, connector, legacyInvocation);
}
}
} catch (JsonException e) {
@@ -444,6 +421,63 @@ public class ServerRpcHandler implements Serializable {
}
/**
+ * Handles the given RPC method invocation for the given connector
+ *
+ * @since
+ * @param ui
+ * the UI containing the connector
+ * @param connector
+ * the connector the RPC is targeted to
+ * @param invocation
+ * information about the rpc to invoke
+ */
+ protected void handleInvocation(UI ui, ClientConnector connector,
+ ServerRpcMethodInvocation invocation) {
+ try {
+ ServerRpcManager.applyInvocation(connector, invocation);
+ } catch (RpcInvocationException e) {
+ ui.getSession().getCommunicationManager()
+ .handleConnectorRelatedException(connector, e);
+ }
+
+ }
+
+ /**
+ * Handles the given Legacy variable change RPC method invocation for the
+ * given connector
+ *
+ * @since
+ * @param ui
+ * the UI containing the connector
+ * @param connector
+ * the connector the RPC is targeted to
+ * @param invocation
+ * information about the rpc to invoke
+ */
+ protected void handleInvocation(UI ui, ClientConnector connector,
+ LegacyChangeVariablesInvocation legacyInvocation) {
+ Map<String, Object> changes = legacyInvocation.getVariableChanges();
+ try {
+ if (connector instanceof VariableOwner) {
+ // The source parameter is never used anywhere
+ changeVariables(null, (VariableOwner) connector, changes);
+ } else {
+ throw new IllegalStateException(
+ "Received legacy variable change for "
+ + connector.getClass().getName()
+ + " ("
+ + connector.getConnectorId()
+ + ") which is not a VariableOwner. The client-side connector sent these legacy varaibles: "
+ + changes.keySet());
+ }
+ } catch (Exception e) {
+ ui.getSession().getCommunicationManager()
+ .handleConnectorRelatedException(connector, e);
+ }
+
+ }
+
+ /**
* Parse JSON from the client into a list of MethodInvocation instances.
*
* @param connectorTracker
diff --git a/server/src/com/vaadin/server/communication/UidlRequestHandler.java b/server/src/com/vaadin/server/communication/UidlRequestHandler.java
index dda3d81453..db18bb9e1e 100644
--- a/server/src/com/vaadin/server/communication/UidlRequestHandler.java
+++ b/server/src/com/vaadin/server/communication/UidlRequestHandler.java
@@ -51,9 +51,20 @@ public class UidlRequestHandler extends SynchronizedRequestHandler implements
public static final String UIDL_PATH = "UIDL/";
- private ServerRpcHandler rpcHandler = new ServerRpcHandler();
+ private ServerRpcHandler rpcHandler;
public UidlRequestHandler() {
+ rpcHandler = createRpcHandler();
+ }
+
+ /**
+ * Creates the ServerRpcHandler to use
+ *
+ * @since
+ * @return the ServerRpcHandler to use
+ */
+ protected ServerRpcHandler createRpcHandler() {
+ return new ServerRpcHandler();
}
@Override
diff --git a/uitest/src/com/vaadin/tests/rpclogger/LoggingServerRpcHandler.java b/uitest/src/com/vaadin/tests/rpclogger/LoggingServerRpcHandler.java
new file mode 100644
index 0000000000..1cb66972ef
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/rpclogger/LoggingServerRpcHandler.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.rpclogger;
+
+import com.vaadin.server.ClientConnector;
+import com.vaadin.server.ServerRpcMethodInvocation;
+import com.vaadin.server.communication.ServerRpcHandler;
+import com.vaadin.shared.communication.LegacyChangeVariablesInvocation;
+import com.vaadin.ui.UI;
+
+public class LoggingServerRpcHandler extends ServerRpcHandler {
+
+ @Override
+ protected void handleInvocation(UI ui, ClientConnector connector,
+ LegacyChangeVariablesInvocation legacyInvocation) {
+ ((RPCLoggerUI) ui).recordInvocation(connector, legacyInvocation);
+ super.handleInvocation(ui, connector, legacyInvocation);
+ }
+
+ @Override
+ protected void handleInvocation(UI ui, ClientConnector connector,
+ ServerRpcMethodInvocation invocation) {
+ ((RPCLoggerUI) ui).recordInvocation(connector, invocation);
+ super.handleInvocation(ui, connector, invocation);
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/rpclogger/LoggingUidlRequestHandler.java b/uitest/src/com/vaadin/tests/rpclogger/LoggingUidlRequestHandler.java
new file mode 100644
index 0000000000..5eff9b56d9
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/rpclogger/LoggingUidlRequestHandler.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.rpclogger;
+
+import com.vaadin.server.communication.ServerRpcHandler;
+import com.vaadin.server.communication.UidlRequestHandler;
+
+public class LoggingUidlRequestHandler extends UidlRequestHandler {
+
+ @Override
+ protected ServerRpcHandler createRpcHandler() {
+ return new LoggingServerRpcHandler();
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/rpclogger/RPCLoggerService.java b/uitest/src/com/vaadin/tests/rpclogger/RPCLoggerService.java
new file mode 100644
index 0000000000..a70a51b603
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/rpclogger/RPCLoggerService.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.rpclogger;
+
+import java.util.List;
+
+import com.vaadin.server.DeploymentConfiguration;
+import com.vaadin.server.RequestHandler;
+import com.vaadin.server.ServiceException;
+import com.vaadin.server.VaadinServlet;
+import com.vaadin.server.VaadinServletService;
+
+public class RPCLoggerService extends VaadinServletService {
+
+ public RPCLoggerService(VaadinServlet servlet,
+ DeploymentConfiguration deploymentConfiguration)
+ throws ServiceException {
+ super(servlet, deploymentConfiguration);
+ }
+
+ @Override
+ protected List<RequestHandler> createRequestHandlers()
+ throws ServiceException {
+ List<RequestHandler> handlers = super.createRequestHandlers();
+ handlers.add(new LoggingUidlRequestHandler());
+ return handlers;
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/rpclogger/RPCLoggerServlet.java b/uitest/src/com/vaadin/tests/rpclogger/RPCLoggerServlet.java
new file mode 100644
index 0000000000..adb4302ba3
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/rpclogger/RPCLoggerServlet.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.rpclogger;
+
+import com.vaadin.server.DeploymentConfiguration;
+import com.vaadin.server.ServiceException;
+import com.vaadin.server.VaadinServlet;
+import com.vaadin.server.VaadinServletService;
+
+public class RPCLoggerServlet extends VaadinServlet {
+
+ @Override
+ protected VaadinServletService createServletService(
+ DeploymentConfiguration deploymentConfiguration)
+ throws ServiceException {
+ RPCLoggerService service = new RPCLoggerService(this,
+ deploymentConfiguration);
+ service.init();
+ return service;
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/rpclogger/RPCLoggerUI.java b/uitest/src/com/vaadin/tests/rpclogger/RPCLoggerUI.java
new file mode 100644
index 0000000000..bac82f232d
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/rpclogger/RPCLoggerUI.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.rpclogger;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import com.vaadin.server.ClientConnector;
+import com.vaadin.server.ErrorHandler;
+import com.vaadin.server.ServerRpcMethodInvocation;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.shared.communication.LegacyChangeVariablesInvocation;
+import com.vaadin.shared.communication.MethodInvocation;
+import com.vaadin.tests.components.AbstractTestUIWithLog;
+import com.vaadin.ui.AbstractComponent;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.Button.ClickListener;
+import com.vaadin.ui.ListSelect;
+import com.vaadin.ui.Notification;
+import com.vaadin.ui.Notification.Type;
+
+public class RPCLoggerUI extends AbstractTestUIWithLog implements ErrorHandler {
+
+ private List<Action> lastActions = new ArrayList<Action>();
+
+ public static class Action {
+ public Action(ClientConnector connector, MethodInvocation invocation) {
+ target = connector;
+ this.invocation = invocation;
+ }
+
+ private MethodInvocation invocation;
+ private ClientConnector target;
+ }
+
+ @Override
+ protected int getLogSize() {
+ return 10;
+ }
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ setErrorHandler(this);
+ addComponent(new Button("Do something"));
+ ListSelect s = new ListSelect();
+ s.setMultiSelect(true);
+ s.addItem("foo");
+ s.addItem("bar");
+ addComponent(s);
+
+ addComponent(new Button("Action, which will fail", new ClickListener() {
+
+ @Override
+ public void buttonClick(ClickEvent event) {
+ throw new RuntimeException("Something went wrong");
+ }
+ }));
+ }
+
+ public void recordInvocation(ClientConnector connector,
+ LegacyChangeVariablesInvocation legacyInvocation) {
+ addAction(new Action(connector, legacyInvocation));
+ }
+
+ public void recordInvocation(ClientConnector connector,
+ ServerRpcMethodInvocation invocation) {
+ addAction(new Action(connector, invocation));
+ }
+
+ private void addAction(Action action) {
+ while (lastActions.size() >= 5) {
+ lastActions.remove(0);
+ }
+ lastActions.add(action);
+ }
+
+ public String formatAction(ClientConnector connector,
+ LegacyChangeVariablesInvocation legacyInvocation) {
+ String connectorIdentifier = getConnectorIdentifier(connector);
+ Map<String, Object> changes = legacyInvocation.getVariableChanges();
+ String rpcInfo = "";
+ for (String key : changes.keySet()) {
+ Object value = changes.get(key);
+ rpcInfo += key + ": " + formatValue(value);
+ }
+ return "Legacy RPC " + rpcInfo + " for " + connectorIdentifier;
+
+ }
+
+ public String formatAction(ClientConnector connector,
+ ServerRpcMethodInvocation invocation) {
+ String connectorIdentifier = getConnectorIdentifier(connector);
+ String rpcInfo = invocation.getInterfaceName() + "."
+ + invocation.getMethodName() + " (";
+ for (Object o : invocation.getParameters()) {
+ rpcInfo += formatValue(o);
+ rpcInfo += ",";
+ }
+ rpcInfo = rpcInfo.substring(0, rpcInfo.length() - 2) + ")";
+ return "RPC " + rpcInfo + " for " + connectorIdentifier;
+
+ }
+
+ private String formatValue(Object value) {
+ if (value == null) {
+ return "null";
+ }
+ if (value instanceof String) {
+ return (String) value;
+ } else if (value instanceof Object[]) {
+ String formatted = "";
+ for (Object o : ((Object[]) value)) {
+ formatted += formatValue(o) + ",";
+ }
+ return formatted;
+ } else {
+ return value.toString();
+ }
+ }
+
+ private String getConnectorIdentifier(ClientConnector connector) {
+ String connectorIdentifier = connector.getClass().getSimpleName();
+ if (connector instanceof AbstractComponent) {
+ String caption = ((AbstractComponent) connector).getCaption();
+ if (caption != null) {
+ connectorIdentifier += " - " + caption;
+ }
+ }
+ return "'" + connectorIdentifier + "'";
+ }
+
+ @Override
+ public void error(com.vaadin.server.ErrorEvent event) {
+ String msg = "";
+
+ for (int i = 0; i < lastActions.size(); i++) {
+ Action action = lastActions.get(i);
+ if (action.invocation instanceof ServerRpcMethodInvocation) {
+ msg += "\n"
+ + (i + 1)
+ + " "
+ + formatAction(action.target,
+ (ServerRpcMethodInvocation) action.invocation);
+ } else {
+ msg += "\n"
+ + (i + 1)
+ + " "
+ + formatAction(
+ action.target,
+ (LegacyChangeVariablesInvocation) action.invocation);
+ }
+ }
+
+ msg += "\n";
+ msg += "\n";
+ msg += "This error should not really be shown but logged for later analysis.";
+ Notification.show(
+ "Something went wrong. Actions leading up to this error were:",
+ msg, Type.ERROR_MESSAGE);
+ // log(msg);
+ }
+}