Browse Source

Properly deserialize push connection (#12235)

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
tags/7.3.0.alpha3
Johannes Dahlström 10 years ago
parent
commit
dca9abccdd

+ 24
- 5
server/src/com/vaadin/server/communication/AtmospherePushConnection.java View 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());
}

}

+ 3
- 1
server/src/com/vaadin/server/communication/PushConnection.java View 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

+ 1
- 2
server/src/com/vaadin/ui/UI.java View 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;
}

}

+ 56
- 0
server/tests/src/com/vaadin/server/communication/AtmospherePushConnectionTest.java View File

@@ -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());
}
}

Loading…
Cancel
Save