From 4863e078780a3d0ca94c4edcc153d1bdfe5a7f92 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Leif=20=C3=85strand?= Date: Thu, 16 Aug 2012 13:42:07 +0300 Subject: [PATCH] Add crude support for only sending state changes (#9026) --- .../server/AbstractCommunicationManager.java | 38 +++++++++++++------ .../vaadin/terminal/gwt/server/JsonCodec.java | 27 ++++++++----- .../src/com/vaadin/ui/ConnectorTracker.java | 13 +++++++ 3 files changed, 56 insertions(+), 22 deletions(-) diff --git a/server/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java b/server/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java index ffee517550..99376ffd1f 100644 --- a/server/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java +++ b/server/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java @@ -68,6 +68,7 @@ import com.vaadin.external.json.JSONException; import com.vaadin.external.json.JSONObject; import com.vaadin.shared.ApplicationConstants; import com.vaadin.shared.Connector; +import com.vaadin.shared.JavaScriptConnectorState; import com.vaadin.shared.Version; import com.vaadin.shared.communication.LegacyChangeVariablesInvocation; import com.vaadin.shared.communication.MethodInvocation; @@ -885,23 +886,36 @@ public abstract class AbstractCommunicationManager implements Serializable { try { Class stateType = connector .getStateType(); - SharedState referenceState = null; - if (repaintAll) { + Object diffState = rootConnectorTracker + .getDiffState(connector); + if (diffState == null) { + diffState = new JSONObject(); // Use an empty state object as reference for full // repaints - try { - referenceState = stateType.newInstance(); - } catch (Exception e) { - getLogger().log( - Level.WARNING, - "Error creating reference object for state of type " - + stateType.getName()); + boolean emptyInitialState = JavaScriptConnectorState.class + .isAssignableFrom(stateType); + if (!emptyInitialState) { + try { + SharedState referenceState = stateType + .newInstance(); + diffState = JsonCodec.encode(referenceState, + null, stateType, + root.getConnectorTracker()); + } catch (Exception e) { + getLogger().log( + Level.WARNING, + "Error creating reference object for state of type " + + stateType.getName()); + } } + rootConnectorTracker.setDiffState(connector, diffState); } - Object stateJson = JsonCodec.encode(state, referenceState, - stateType, root.getConnectorTracker()); + JSONObject stateJson = (JSONObject) JsonCodec.encode(state, + diffState, stateType, root.getConnectorTracker()); - sharedStates.put(connector.getConnectorId(), stateJson); + if (stateJson.length() != 0) { + sharedStates.put(connector.getConnectorId(), stateJson); + } } catch (JSONException e) { throw new PaintException( "Failed to serialize shared state for connector " diff --git a/server/src/com/vaadin/terminal/gwt/server/JsonCodec.java b/server/src/com/vaadin/terminal/gwt/server/JsonCodec.java index 94d860a200..884e01f9a5 100644 --- a/server/src/com/vaadin/terminal/gwt/server/JsonCodec.java +++ b/server/src/com/vaadin/terminal/gwt/server/JsonCodec.java @@ -526,9 +526,8 @@ public class JsonCodec implements Serializable { } } - public static Object encode(Object value, Object referenceValue, - Type valueType, ConnectorTracker connectorTracker) - throws JSONException { + public static Object encode(Object value, Object diffState, Type valueType, + ConnectorTracker connectorTracker) throws JSONException { if (valueType == null) { throw new IllegalArgumentException("type must be defined"); @@ -595,7 +594,7 @@ public class JsonCodec implements Serializable { } else { // Any object that we do not know how to encode we encode by looping // through fields - return encodeObject(value, referenceValue, connectorTracker); + return encodeObject(value, (JSONObject) diffState, connectorTracker); } } @@ -603,7 +602,7 @@ public class JsonCodec implements Serializable { return JSONObject.NULL; } - private static Object encodeObject(Object value, Object referenceValue, + private static Object encodeObject(Object value, JSONObject diffState, ConnectorTracker connectorTracker) throws JSONException { JSONObject jsonMap = new JSONObject(); @@ -620,10 +619,11 @@ public class JsonCodec implements Serializable { Type fieldType = getterMethod.getGenericReturnType(); Object fieldValue = getterMethod.invoke(value, (Object[]) null); boolean equals = false; - Object referenceFieldValue = null; - if (referenceValue != null) { - referenceFieldValue = getterMethod.invoke(referenceValue, - (Object[]) null); + Object diffStateValue = null; + if (diffState != null) { + diffStateValue = diffState.get(fieldName); + Object referenceFieldValue = decodeInternalOrCustomType( + fieldType, diffStateValue, connectorTracker); equals = equals(fieldValue, referenceFieldValue); } if (!equals) { @@ -637,8 +637,15 @@ public class JsonCodec implements Serializable { } jsonMap.put( fieldName, - encode(fieldValue, referenceFieldValue, fieldType, + encode(fieldValue, diffStateValue, fieldType, connectorTracker)); + if (diffState != null) { + diffState.put( + fieldName, + encode(fieldValue, null, fieldType, + connectorTracker)); + } + // } else { // System.out.println("Skipping field " + fieldName // + " of type " + fieldType.getName() diff --git a/server/src/com/vaadin/ui/ConnectorTracker.java b/server/src/com/vaadin/ui/ConnectorTracker.java index 27dfebd95e..f16642d91b 100644 --- a/server/src/com/vaadin/ui/ConnectorTracker.java +++ b/server/src/com/vaadin/ui/ConnectorTracker.java @@ -20,6 +20,7 @@ import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.Map; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; @@ -54,6 +55,7 @@ public class ConnectorTracker implements Serializable { private Set uninitializedConnectors = new HashSet(); private Root root; + private Map diffStates = new HashMap(); /** * Gets a logger for this class @@ -140,6 +142,7 @@ public class ConnectorTracker implements Serializable { + connectorId + ")"); connectorIdToConnector.remove(connectorId); uninitializedConnectors.remove(connector); + diffStates.remove(connector); } /** @@ -180,6 +183,7 @@ public class ConnectorTracker implements Serializable { */ public void markAllClientSidesUninitialized() { uninitializedConnectors.addAll(connectorIdToConnector.values()); + diffStates.clear(); } /** @@ -220,6 +224,7 @@ public class ConnectorTracker implements Serializable { + getConnectorAndParentInfo(connector) + "). This should have been done when the connector was detached."); uninitializedConnectors.remove(connector); + diffStates.remove(connector); iterator.remove(); } } @@ -372,4 +377,12 @@ public class ConnectorTracker implements Serializable { return dirtyConnectors; } + public Object getDiffState(ClientConnector connector) { + return diffStates.get(connector); + } + + public void setDiffState(ClientConnector connector, Object diffState) { + diffStates.put(connector, diffState); + } + } -- 2.39.5