]> source.dussan.org Git - vaadin-framework.git/commitdiff
fix: set Vaadin session attribute using lock in reinitializeSession (#12401)
authorTatu Lund <tatu@vaadin.com>
Thu, 16 Sep 2021 09:23:56 +0000 (12:23 +0300)
committerGitHub <noreply@github.com>
Thu, 16 Sep 2021 09:23:56 +0000 (12:23 +0300)
* Cherry picked unit test from Flow

See https://github.com/vaadin/flow/pull/11538

* Fix missing import

* Cherry pick fix from Flow

server/src/main/java/com/vaadin/server/VaadinService.java
server/src/test/java/com/vaadin/server/VaadinServiceTest.java

index 888b82a3cb7a42e7696867a447258fe4d31912f8..25354074e1fb448174c00a9cfa4a843404dc390a 100644 (file)
@@ -1156,8 +1156,13 @@ public abstract class VaadinService implements Serializable {
             if (value instanceof VaadinSession) {
                 // set flag to avoid cleanup
                 VaadinSession serviceSession = (VaadinSession) value;
-                serviceSession.setAttribute(PRESERVE_UNBOUND_SESSION_ATTRIBUTE,
-                        Boolean.TRUE);
+                serviceSession.lock();
+                try {
+                    serviceSession.setAttribute(
+                            PRESERVE_UNBOUND_SESSION_ATTRIBUTE, Boolean.TRUE);
+                } finally {
+                    serviceSession.unlock();
+                }
             }
             attrs.put(name, value);
         }
@@ -1183,8 +1188,13 @@ public abstract class VaadinService implements Serializable {
                         serviceSession.getLockInstance());
 
                 service.storeSession(serviceSession, newSession);
-                serviceSession.setAttribute(PRESERVE_UNBOUND_SESSION_ATTRIBUTE,
-                        null);
+                serviceSession.lock();
+                try {
+                    serviceSession.setAttribute(
+                            PRESERVE_UNBOUND_SESSION_ATTRIBUTE, null);
+                } finally {
+                    serviceSession.unlock();
+                }
             }
         }
 
index f10f55db362f617b51f1829bfdc3d33109337ae0..f179ad1d58786598871eebe0098edf7dc028218f 100644 (file)
@@ -8,8 +8,11 @@ import javax.servlet.ServletConfig;
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpSessionBindingEvent;
 
+import java.util.Collections;
+
 import org.easymock.EasyMock;
 import org.junit.Test;
+import org.mockito.Mockito;
 
 import com.vaadin.shared.Registration;
 import com.vaadin.util.CurrentInstance;
@@ -179,4 +182,45 @@ public class VaadinServiceTest {
         assertEquals(1, listener.callCount);
         assertEquals(1, listener2.callCount);
     }
+
+    @Test
+    public void reinitializeSession_setVaadinSessionAttriuteWithLock() {
+        VaadinRequest request = Mockito.mock(VaadinRequest.class);
+
+        VaadinSession vaadinSession = Mockito.mock(VaadinSession.class);
+        VaadinSession newVaadinSession = Mockito.mock(VaadinSession.class);
+
+        WrappedSession session = mockSession(request, vaadinSession, "foo");
+
+        Mockito.doAnswer(invocation -> {
+            mockSession(request, newVaadinSession, "bar");
+            return null;
+        }).when(session).invalidate();
+
+        VaadinService.reinitializeSession(request);
+
+        Mockito.verify(vaadinSession, Mockito.times(2)).lock();
+        Mockito.verify(vaadinSession).setAttribute(
+                VaadinService.PRESERVE_UNBOUND_SESSION_ATTRIBUTE, Boolean.TRUE);
+        Mockito.verify(vaadinSession).setAttribute(
+                VaadinService.PRESERVE_UNBOUND_SESSION_ATTRIBUTE, null);
+        Mockito.verify(vaadinSession, Mockito.times(2)).unlock();
+    }
+
+    private WrappedSession mockSession(VaadinRequest request,
+            VaadinSession vaadinSession, String attributeName) {
+        WrappedSession session = Mockito.mock(WrappedSession.class);
+        Mockito.when(request.getWrappedSession()).thenReturn(session);
+
+        Mockito.when(session.getAttributeNames())
+                .thenReturn(Collections.singleton(attributeName));
+
+        Mockito.when(session.getAttribute(attributeName))
+                .thenReturn(vaadinSession);
+
+        VaadinService service = Mockito.mock(VaadinService.class);
+
+        Mockito.when(vaadinSession.getService()).thenReturn(service);
+        return session;
+    }
 }