PushConnection is not serializable #3753

Closed
vaadin-bot opened this Issue Apr 5, 2013 · 3 comments

Comments

Projects
None yet
1 participant
@vaadin-bot
Collaborator

vaadin-bot commented Apr 5, 2013

Originally by @Legioth


If push is not enabled and Atmosphere is not on the classpath, serializing a UI instance causes this exception as the pushConnection field in UI is always initialized:

Caused by: java.lang.NoClassDefFoundError: Lorg/atmosphere/cpr/AtmosphereResource;
        at java.lang.Class.getDeclaredFields0(Native Method)
        at java.lang.Class.privateGetDeclaredFields(Class.java:2291)
        at java.lang.Class.getDeclaredField(Class.java:1880)
        at java.io.ObjectStreamClass.getDeclaredSUID(ObjectStreamClass.java:1605)
        at java.io.ObjectStreamClass.access$700(ObjectStreamClass.java:50)
        at java.io.ObjectStreamClass$2.run(ObjectStreamClass.java:423)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.io.ObjectStreamClass.<init>(ObjectStreamClass.java:411)
        at java.io.ObjectStreamClass.lookup(ObjectStreamClass.java:308)
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1114)
        at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
        at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
        at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
        at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:330)
        at com.vaadin.tests.components.ui.UISerialization.serialize(UISerialization.java:76)
        at com.vaadin.tests.components.ui.UISerialization$1.buttonClick(UISerialization.java:45)
        at sun.reflect.GeneratedMethodAccessor13.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at com.vaadin.event.ListenerMethod.receiveEvent(ListenerMethod.java:508)
        ... 42 more

Caused by the PushConnection field in UI, which has a non-transient AtmosphereResource.

If push is instead enabled, the serialization will fail with the message in the comment bellow because org.atmosphere.cpr.AtmosphereResourceImpl is not serializable. For this case, the general case could be supported by making the AtmosphereResource field transient and restoring it in PushHandler. The problem is however that pushing will then fail for a UI that has recently been deserialized but not yet received any request from the client.

@vaadin-bot

This comment has been minimized.

Show comment Hide comment
@vaadin-bot

vaadin-bot Apr 8, 2013

Collaborator

Originally by @Legioth


Similar problem when serializing a UI instance with push enabled and on the classpath:

java.io.NotSerializableException: org.atmosphere.cpr.AtmosphereResourceImpl
	- field (class "com.vaadin.server.communication.PushConnection", name: "resource", type: "interface org.atmosphere.cpr.AtmosphereResource")
	- object (class "com.vaadin.server.communication.PushConnection", com.vaadin.server.communication.PushConnection@6267fe80)
	- field (class "com.vaadin.ui.UI", name: "pushConnection", type: "class com.vaadin.server.communication.PushConnection")
	- object (class "org.vaadin.example.MyUI", org.vaadin.example.MyUI@57f5b4d1)
	- custom writeObject data (class "java.util.HashMap")
	- object (class "java.util.HashMap", {0=org.vaadin.example.MyUI@57f5b4d1})
	- field (class "com.vaadin.server.VaadinSession", name: "uIs", type: "interface java.util.Map")
	- object (class "com.vaadin.server.VaadinSession", com.vaadin.server.VaadinSession@7c83d8be)
	- field (class "com.vaadin.ui.UI", name: "session", type: "class com.vaadin.server.VaadinSession")
	- root object (class "org.vaadin.example.MyUI", org.vaadin.example.MyUI@6e8ef177)
	at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1161)
	at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
	at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
	at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
	at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
	at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
	at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
	at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
	at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
	at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:330)
	at java.util.HashMap.writeObject(HashMap.java:1001)
	at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:940)
	at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1469)
	at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
	at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
	at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
	at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
	at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
	at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
	at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
	at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
	at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
	at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
	at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:330)
Collaborator

vaadin-bot commented Apr 8, 2013

Originally by @Legioth


Similar problem when serializing a UI instance with push enabled and on the classpath:

java.io.NotSerializableException: org.atmosphere.cpr.AtmosphereResourceImpl
	- field (class "com.vaadin.server.communication.PushConnection", name: "resource", type: "interface org.atmosphere.cpr.AtmosphereResource")
	- object (class "com.vaadin.server.communication.PushConnection", com.vaadin.server.communication.PushConnection@6267fe80)
	- field (class "com.vaadin.ui.UI", name: "pushConnection", type: "class com.vaadin.server.communication.PushConnection")
	- object (class "org.vaadin.example.MyUI", org.vaadin.example.MyUI@57f5b4d1)
	- custom writeObject data (class "java.util.HashMap")
	- object (class "java.util.HashMap", {0=org.vaadin.example.MyUI@57f5b4d1})
	- field (class "com.vaadin.server.VaadinSession", name: "uIs", type: "interface java.util.Map")
	- object (class "com.vaadin.server.VaadinSession", com.vaadin.server.VaadinSession@7c83d8be)
	- field (class "com.vaadin.ui.UI", name: "session", type: "class com.vaadin.server.VaadinSession")
	- root object (class "org.vaadin.example.MyUI", org.vaadin.example.MyUI@6e8ef177)
	at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1161)
	at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
	at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
	at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
	at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
	at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
	at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
	at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
	at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
	at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:330)
	at java.util.HashMap.writeObject(HashMap.java:1001)
	at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:940)
	at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1469)
	at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
	at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
	at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
	at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
	at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
	at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
	at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
	at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
	at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
	at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
	at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:330)
@vaadin-bot

This comment has been minimized.

Show comment Hide comment
@vaadin-bot

vaadin-bot Apr 11, 2013

Collaborator

Originally by @jdahlstrom


Might be enough to make PushConnection.resource transient. If, after deserialization, the resource field is null, the situation should be exactly the same as with a new UI that's not yet connected. PushHandler will re-connect the UI once it gets a request from the client, and any server pushes are deferred until the connection is re-established.

The only difference is if there can be a situation where the session is serialized and later deserialized but the connection somehow survives. We should probably assert connection.isConnected() in the PushHandler.onRequest POST branch to keep an eye on it.

Collaborator

vaadin-bot commented Apr 11, 2013

Originally by @jdahlstrom


Might be enough to make PushConnection.resource transient. If, after deserialization, the resource field is null, the situation should be exactly the same as with a new UI that's not yet connected. PushHandler will re-connect the UI once it gets a request from the client, and any server pushes are deferred until the connection is re-established.

The only difference is if there can be a situation where the session is serialized and later deserialized but the connection somehow survives. We should probably assert connection.isConnected() in the PushHandler.onRequest POST branch to keep an eye on it.

@vaadin-bot

This comment has been minimized.

Show comment Hide comment
@vaadin-bot

vaadin-bot Apr 12, 2013

Collaborator

Originally by @Legioth


Reviewed by Johannes Dahlström

Collaborator

vaadin-bot commented Apr 12, 2013

Originally by @Legioth


Reviewed by Johannes Dahlström

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment