]> source.dussan.org Git - vaadin-framework.git/commitdiff
Properly deserialize push connection (#12235)
authorJohannes Dahlström <johannesd@vaadin.com>
Mon, 19 May 2014 13:28:09 +0000 (16:28 +0300)
committerArtur Signell <artur@vaadin.com>
Mon, 26 May 2014 13:18:00 +0000 (13:18 +0000)
The UI.pushConnection field is transient no longer; instead PushConnection
implementations must take care of serialization internally. When a session
is serialized, the client should notice that push was disconnected and
try to reconnect. A deserialized PushConnection should be in a "disconnected"
state so the eventual client reconnection works correctly.

Change-Id: I38cfc5a5cdbd3643311f830f8d580458dcd85c56

server/src/com/vaadin/server/communication/AtmospherePushConnection.java
server/src/com/vaadin/server/communication/PushConnection.java
server/src/com/vaadin/ui/UI.java
server/tests/src/com/vaadin/server/communication/AtmospherePushConnectionTest.java [new file with mode: 0644]

index 3eae848adce9c36b0ddd35e9beed735b3096412f..f8ef360eda415a5d8596226c2e87c119a39ac5ef 100644 (file)
@@ -17,6 +17,7 @@
 package com.vaadin.server.communication;
 
 import java.io.IOException;
+import java.io.ObjectInputStream;
 import java.io.Reader;
 import java.io.Serializable;
 import java.io.StringReader;
@@ -117,11 +118,11 @@ public class AtmospherePushConnection implements PushConnection {
         CONNECTED;
     }
 
-    private State state = State.DISCONNECTED;
     private UI ui;
-    private AtmosphereResource resource;
-    private FragmentedMessage incomingMessage;
-    private Future<Object> outgoingMessage;
+    private transient State state = State.DISCONNECTED;
+    private transient AtmosphereResource resource;
+    private transient FragmentedMessage incomingMessage;
+    private transient Future<Object> outgoingMessage;
 
     public AtmospherePushConnection(UI ui) {
         this.ui = ui;
@@ -209,6 +210,7 @@ public class AtmospherePushConnection implements PushConnection {
 
     @Override
     public boolean isConnected() {
+        assert state != null;
         assert (state == State.CONNECTED) ^ (resource == null);
         return state == State.CONNECTED;
     }
@@ -297,8 +299,25 @@ public class AtmospherePushConnection implements PushConnection {
         state = State.DISCONNECTED;
     }
 
+    /**
+     * Returns the state of this connection.
+     */
+    protected State getState() {
+        return state;
+    }
+
+    /**
+     * Reinitializes this PushConnection after deserialization. The connection
+     * is initially in disconnected state; the client will handle the
+     * reconnecting.
+     */
+    private void readObject(ObjectInputStream stream) throws IOException,
+            ClassNotFoundException {
+        stream.defaultReadObject();
+        state = State.DISCONNECTED;
+    }
+
     private static Logger getLogger() {
         return Logger.getLogger(AtmospherePushConnection.class.getName());
     }
-
 }
index 52efcfcd89827f86580f685e810f7ad2a128fb0f..d5a0d6e9bcbbef4ed9a6d2803ec774074421a388 100644 (file)
@@ -16,6 +16,8 @@
 
 package com.vaadin.server.communication;
 
+import java.io.Serializable;
+
 import com.vaadin.ui.UI;
 
 /**
@@ -30,7 +32,7 @@ import com.vaadin.ui.UI;
  * @author Vaadin Ltd
  * @since 7.1
  */
-public interface PushConnection {
+public interface PushConnection extends Serializable {
 
     /**
      * Pushes pending state changes and client RPC calls to the client. Can be
index 7a71083e85224bb769e51084f1cc1eea678fe93f..562b30f81df846e9efa556c6e26357f8590f1303 100644 (file)
@@ -553,7 +553,7 @@ public abstract class UI extends AbstractSingleComponentContainer implements
 
     private Navigator navigator;
 
-    private transient PushConnection pushConnection = null;
+    private PushConnection pushConnection = null;
 
     private LocaleService localeService = new LocaleService(this,
             getState(false).localeServiceState);
@@ -1626,5 +1626,4 @@ public abstract class UI extends AbstractSingleComponentContainer implements
     public String getEmbedId() {
         return embedId;
     }
-
 }
diff --git a/server/tests/src/com/vaadin/server/communication/AtmospherePushConnectionTest.java b/server/tests/src/com/vaadin/server/communication/AtmospherePushConnectionTest.java
new file mode 100644 (file)
index 0000000..f9e12ce
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.server.communication;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import org.atmosphere.cpr.AtmosphereResource;
+import org.easymock.EasyMock;
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.server.communication.AtmospherePushConnection.State;
+import com.vaadin.ui.UI;
+
+/**
+ * @author Vaadin Ltd
+ */
+public class AtmospherePushConnectionTest {
+    @Test
+    public void testSerialization() throws Exception {
+
+        UI ui = EasyMock.createNiceMock(UI.class);
+        AtmosphereResource resource = EasyMock
+                .createNiceMock(AtmosphereResource.class);
+
+        AtmospherePushConnection connection = new AtmospherePushConnection(ui);
+        connection.connect(resource);
+
+        Assert.assertEquals(State.CONNECTED, connection.getState());
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+        new ObjectOutputStream(baos).writeObject(connection);
+
+        connection = (AtmospherePushConnection) new ObjectInputStream(
+                new ByteArrayInputStream(baos.toByteArray())).readObject();
+
+        Assert.assertEquals(State.DISCONNECTED, connection.getState());
+    }
+}