]> source.dussan.org Git - vaadin-framework.git/commitdiff
Set session as current while deserializing (#9953)
authorLeif Åstrand <leif@vaadin.com>
Mon, 26 Oct 2015 15:44:44 +0000 (15:44 +0000)
committerVaadin Code Review <review@vaadin.com>
Wed, 25 Nov 2015 09:21:51 +0000 (09:21 +0000)
Change-Id: Ib420f99c621b7d508659907615a7e8a1ae47b4d9

server/src/com/vaadin/server/VaadinSession.java
server/tests/src/com/vaadin/server/VaadinSessionTest.java

index ab246949641960199b9208756297d8e6154a0582..bcc07acb99c1df368402161d58ce6edd5a988a79 100644 (file)
@@ -1410,8 +1410,13 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
      */
     private void readObject(ObjectInputStream stream) throws IOException,
             ClassNotFoundException {
-        stream.defaultReadObject();
-        pendingAccessQueue = new ConcurrentLinkedQueue<FutureAccess>();
+        Map<Class<?>, CurrentInstance> old = CurrentInstance.setCurrent(this);
+        try {
+            stream.defaultReadObject();
+            pendingAccessQueue = new ConcurrentLinkedQueue<FutureAccess>();
+        } finally {
+            CurrentInstance.restoreInstances(old);
+        }
     }
 
     /**
index 4944d3785688e92b01b46deadc062c187d56cedd..0e50abecff95be0c44daa91703163c34c2a455fc 100644 (file)
  */
 package com.vaadin.server;
 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.locks.Lock;
@@ -33,6 +38,7 @@ import org.junit.Test;
 import com.vaadin.server.ClientConnector.DetachEvent;
 import com.vaadin.server.ClientConnector.DetachListener;
 import com.vaadin.server.communication.UIInitHandler;
+import com.vaadin.ui.Label;
 import com.vaadin.ui.UI;
 import com.vaadin.util.CurrentInstance;
 
@@ -95,22 +101,7 @@ public class VaadinSessionTest {
         session = new VaadinSession(mockService);
         mockService.storeSession(session, mockWrappedSession);
 
-        ui = new UI() {
-            Page page = new Page(this, getState(false).pageState) {
-                @Override
-                public void init(VaadinRequest request) {
-                }
-            };
-
-            @Override
-            protected void init(VaadinRequest request) {
-            }
-
-            @Override
-            public Page getPage() {
-                return page;
-            }
-        };
+        ui = new MockPageUI();
         vaadinRequest = new VaadinServletRequest(
                 EasyMock.createMock(HttpServletRequest.class), mockService) {
             @Override
@@ -249,4 +240,80 @@ public class VaadinSessionTest {
                         + "method for closing session", 1,
                 vaadinSession.getCloseCount());
     }
+
+    // Can't define as an anonymous class since it would have a reference to
+    // VaadinSessionTest.this which isn't serializable
+    private static class MockPageUI extends UI {
+        Page page = new Page(this, getState(false).pageState) {
+            @Override
+            public void init(VaadinRequest request) {
+            }
+        };
+
+        @Override
+        protected void init(VaadinRequest request) {
+        }
+
+        @Override
+        public Page getPage() {
+            return page;
+        }
+    }
+
+    private static class SerializationTestLabel extends Label {
+        private transient VaadinSession session = VaadinSession.getCurrent();
+
+        private void readObject(ObjectInputStream in) throws IOException,
+                ClassNotFoundException {
+            in.defaultReadObject();
+            session = VaadinSession.getCurrent();
+        }
+    }
+
+    @Test
+    public void threadLocalsWhenDeserializing() throws Exception {
+        VaadinSession.setCurrent(session);
+        session.lock();
+        SerializationTestLabel label = new SerializationTestLabel();
+        Assert.assertEquals("Session should be set when instance is created",
+                session, label.session);
+
+        ui.setContent(label);
+        int uiId = ui.getUIId();
+
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        ObjectOutputStream out = new ObjectOutputStream(bos);
+        out.writeObject(session);
+        out.close();
+
+        session.unlock();
+
+        CurrentInstance.clearAll();
+
+        ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(
+                bos.toByteArray()));
+
+        VaadinSession deserializedSession = (VaadinSession) in.readObject();
+
+        Assert.assertNull(
+                "Current session shouldn't leak from deserialisation",
+                VaadinSession.getCurrent());
+
+        Assert.assertNotSame("Should get a new session", session,
+                deserializedSession);
+
+        // Restore http session and service instance so the session can be
+        // locked
+        deserializedSession.refreshTransients(mockWrappedSession, mockService);
+        deserializedSession.lock();
+
+        UI deserializedUi = deserializedSession.getUIById(uiId);
+        SerializationTestLabel deserializedLabel = (SerializationTestLabel) deserializedUi
+                .getContent();
+
+        Assert.assertEquals(
+                "Current session should be available in SerializationTestLabel.readObject",
+                deserializedSession, deserializedLabel.session);
+        deserializedSession.unlock();
+    }
 }