diff options
author | Leif Åstrand <leif@vaadin.com> | 2016-02-14 12:17:10 +0200 |
---|---|---|
committer | Leif Åstrand <leif@vaadin.com> | 2016-02-14 13:08:59 +0200 |
commit | 493e5d7f460cf6c41b858ac6e0abafe177f4a71c (patch) | |
tree | a5cb03dc96641f9507b3e9a8f17380ccc44fd08b | |
parent | 0225d0949b566dd6913aef44840cd9ae6c399c28 (diff) | |
download | vaadin-framework-493e5d7f460cf6c41b858ac6e0abafe177f4a71c.tar.gz vaadin-framework-493e5d7f460cf6c41b858ac6e0abafe177f4a71c.zip |
Lock session during deserialization (#19310)
Change-Id: I0f0c029d6de88b74bae1c7253b7665d5570e3767
-rw-r--r-- | server/src/com/vaadin/server/VaadinSession.java | 21 | ||||
-rw-r--r-- | server/tests/src/com/vaadin/server/VaadinSessionTest.java | 44 |
2 files changed, 55 insertions, 10 deletions
diff --git a/server/src/com/vaadin/server/VaadinSession.java b/server/src/com/vaadin/server/VaadinSession.java index bcc07acb99..304dd4bec6 100644 --- a/server/src/com/vaadin/server/VaadinSession.java +++ b/server/src/com/vaadin/server/VaadinSession.java @@ -18,6 +18,7 @@ package com.vaadin.server; import java.io.IOException; import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.io.Serializable; import java.lang.reflect.Method; import java.util.Collection; @@ -1420,6 +1421,26 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { } /** + * Override default serialization logic to avoid + * ConcurrentModificationException if the contents are modified while + * serialization is reading them. + */ + private void writeObject(ObjectOutputStream out) throws IOException { + Lock lock = this.lock; + + if (lock != null) { + lock.lock(); + } + try { + out.defaultWriteObject(); + } finally { + if (lock != null) { + lock.unlock(); + } + } + } + + /** * Finds the UI with the corresponding embed id. * * @since 7.2 diff --git a/server/tests/src/com/vaadin/server/VaadinSessionTest.java b/server/tests/src/com/vaadin/server/VaadinSessionTest.java index 0e50abecff..85c37d156c 100644 --- a/server/tests/src/com/vaadin/server/VaadinSessionTest.java +++ b/server/tests/src/com/vaadin/server/VaadinSessionTest.java @@ -20,6 +20,7 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; +import java.io.Serializable; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.Lock; @@ -42,17 +43,17 @@ import com.vaadin.ui.Label; import com.vaadin.ui.UI; import com.vaadin.util.CurrentInstance; -public class VaadinSessionTest { +public class VaadinSessionTest implements Serializable { - private VaadinSession session; - private VaadinServlet mockServlet; - private VaadinServletService mockService; - private ServletConfig mockServletConfig; - private HttpSession mockHttpSession; - private WrappedSession mockWrappedSession; - private VaadinServletRequest vaadinRequest; - private UI ui; - private Lock httpSessionLock; + private transient VaadinSession session; + private transient VaadinServlet mockServlet; + private transient VaadinServletService mockService; + private transient ServletConfig mockServletConfig; + private transient HttpSession mockHttpSession; + private transient WrappedSession mockWrappedSession; + private transient VaadinServletRequest vaadinRequest; + private transient UI ui; + private transient Lock httpSessionLock; @Before public void setup() throws Exception { @@ -316,4 +317,27 @@ public class VaadinSessionTest { deserializedSession, deserializedLabel.session); deserializedSession.unlock(); } + + @Test + public void lockedDuringSerialization() throws IOException { + final AtomicBoolean lockChecked = new AtomicBoolean(false); + + ui.setContent(new Label() { + private void writeObject(ObjectOutputStream out) throws IOException { + Assert.assertTrue(session.hasLock()); + lockChecked.set(true); + out.defaultWriteObject(); + } + }); + + session.unlock(); + Assert.assertFalse(session.hasLock()); + + ObjectOutputStream out = new ObjectOutputStream( + new ByteArrayOutputStream()); + out.writeObject(session); + + Assert.assertFalse(session.hasLock()); + Assert.assertTrue(lockChecked.get()); + } } |