]> source.dussan.org Git - vaadin-framework.git/commitdiff
Do not modify state while serializing (#19090)
authorArtur Signell <artur@vaadin.com>
Fri, 9 Oct 2015 20:44:47 +0000 (23:44 +0300)
committerTeemu Suo-Anttila <teemusa@vaadin.com>
Fri, 27 Nov 2015 09:40:49 +0000 (11:40 +0200)
Serializing an object should never modify its internal state.
It should be possible to serialize an object multiple times and get
the same result

Change-Id: I79502274179a646f8b0cd8d1fc4cbfd84867299d

server/src/com/vaadin/server/ClientMethodInvocation.java
server/tests/src/com/vaadin/tests/server/ClientMethodSerializationTest.java

index 33b88a168b1d0ef24a77d2066b4e9e7bab38c116..77849c83dfbc4da62e1cfbdc11575ed971d5dad5 100644 (file)
@@ -38,7 +38,7 @@ public class ClientMethodInvocation implements Serializable,
     private final ClientConnector connector;
     private final String interfaceName;
     private final String methodName;
-    private final Object[] parameters;
+    private transient Object[] parameters;
     private Type[] parameterTypes;
 
     // used for sorting calls between different connectors in the same UI
@@ -102,6 +102,7 @@ public class ClientMethodInvocation implements Serializable,
         // that is Serializable. On deserialization (readObject-method below)
         // the process should be reversed.
 
+        Object[] serializedParameters = new Object[parameters.length];
         // Easy way for implementing serialization & deserialization is by
         // writing/parsing the object's content as string.
         for (int i = 0; i < parameterTypes.length; i++) {
@@ -109,12 +110,15 @@ public class ClientMethodInvocation implements Serializable,
             if (type instanceof Class<?>) {
                 Class<?> clazz = (Class<?>) type;
                 if (JsonArray.class.isAssignableFrom(clazz)) {
-                    parameters[i] = JsonUtil
+                    serializedParameters[i] = JsonUtil
                             .stringify((JsonArray) parameters[i]);
+                } else {
+                    serializedParameters[i] = parameters[i];
                 }
             }
         }
         stream.defaultWriteObject();
+        stream.writeObject(serializedParameters);
     }
 
     private void readObject(ObjectInputStream stream) throws IOException,
@@ -122,6 +126,7 @@ public class ClientMethodInvocation implements Serializable,
         // Reverses the serialization done in writeObject. Basically just
         // parsing the serialized type back to the non-serializable type.
         stream.defaultReadObject();
+        parameters = (Object[]) stream.readObject();
         for (int i = 0; i < parameterTypes.length; i++) {
             Type type = parameterTypes[i];
             if (type instanceof Class<?>) {
index da6bc76a0fedd9b0901951004b6e421f025e38ae..1ec19724d81e4c57954b396c1dbd4eba931d85b1 100644 (file)
@@ -24,13 +24,16 @@ import java.lang.reflect.Method;
 
 import junit.framework.TestCase;
 
+import com.vaadin.server.ClientConnector;
 import com.vaadin.server.ClientMethodInvocation;
 import com.vaadin.server.JavaScriptCallbackHelper;
+import com.vaadin.server.JsonCodec;
 import com.vaadin.ui.JavaScript.JavaScriptCallbackRpc;
 import com.vaadin.util.ReflectTools;
 
 import elemental.json.Json;
 import elemental.json.JsonArray;
+import elemental.json.JsonValue;
 import elemental.json.impl.JsonUtil;
 
 public class ClientMethodSerializationTest extends TestCase {
@@ -112,4 +115,31 @@ public class ClientMethodSerializationTest extends TestCase {
         return output;
     }
 
+    public void testSerializeTwice() {
+        String name = "javascriptFunctionName";
+        String[] arguments = { "1", "2", "3" };
+        JsonArray args = (JsonArray) JsonCodec.encode(arguments, null,
+                Object[].class, null).getEncodedValue();
+        ClientConnector connector = null;
+
+        ClientMethodInvocation original = new ClientMethodInvocation(connector,
+                "interfaceName", JAVASCRIPT_CALLBACK_METHOD, new Object[] {
+                        name, args });
+
+        ClientMethodInvocation copy = (ClientMethodInvocation) serializeAndDeserialize(original);
+        assertEquals(copy.getMethodName(), original.getMethodName());
+        assertEquals(copy.getParameters().length,
+                original.getParameters().length);
+        for (int i = 0; i < copy.getParameters().length; i++) {
+            Object originalParameter = original.getParameters()[i];
+            Object copyParameter = copy.getParameters()[i];
+            if (originalParameter instanceof JsonValue) {
+                assertEquals(((JsonValue) originalParameter).toJson(),
+                        ((JsonValue) copyParameter).toJson());
+            } else {
+                assertEquals(originalParameter, copyParameter);
+            }
+        }
+    }
+
 }