0

My sample app configuration: Java 8, Vaadin 7.5.6; Deploy at Apache Tomcat 8.0.24.

From time to time after redeploy, I obtain some exceptions at server startup. For example today at startup:

2015-10-29 09:54:15 ERROR StandardManager - standardManager.loading.ioe
java.io.InvalidClassException: com.vaadin.server.WebBrowser; local class incompatible: stream classdesc serialVersionUID = -4707470459521903161, local class serialVersionUID = 1931594131304735556
        at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:621) ~[?:1.8.0_51]
        at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1623) ~[?:1.8.0_51]
        at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1518) ~[?:1.8.0_51]
        at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1774) ~[?:1.8.0_51]
        at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351) ~[?:1.8.0_51]
        at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2000) ~[?:1.8.0_51]
        at java.io.ObjectInputStream.defaultReadObject(ObjectInputStream.java:501) ~[?:1.8.0_51]
        at com.vaadin.server.VaadinSession.readObject(VaadinSession.java:1443) ~[vaadin-server-7.5.6.jar:?]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_51]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_51]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_51]
        at java.lang.reflect.Method.invoke(Method.java:497) ~[?:1.8.0_51]
        at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1017) ~[?:1.8.0_51]
        at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1900) ~[?:1.8.0_51]
        at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1801) ~[?:1.8.0_51]
        at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351) ~[?:1.8.0_51]
        at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371) ~[?:1.8.0_51]
        at org.apache.catalina.session.StandardSession.doReadObject(StandardSession.java:1634) ~[catalina.jar:8.0.24]
        at org.apache.catalina.session.StandardSession.readObjectData(StandardSession.java:1099) ~[catalina.jar:8.0.24]
        at org.apache.catalina.session.StandardManager.doLoad(StandardManager.java:261) [catalina.jar:8.0.24]
        at org.apache.catalina.session.StandardManager.load(StandardManager.java:180) [catalina.jar:8.0.24]
        at org.apache.catalina.session.StandardManager.startInternal(StandardManager.java:460) [catalina.jar:8.0.24]
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) [catalina.jar:8.0.24]
        at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5184) [catalina.jar:8.0.24]
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) [catalina.jar:8.0.24]
        at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:725) [catalina.jar:8.0.24]
        at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:701) [catalina.jar:8.0.24]
        at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:717) [catalina.jar:8.0.24]
        at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:945) [catalina.jar:8.0.24]
        at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1768) [catalina.jar:8.0.24]
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [?:1.8.0_51]
        at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:1.8.0_51]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [?:1.8.0_51]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [?:1.8.0_51]
        at java.lang.Thread.run(Thread.java:745) [?:1.8.0_51]
2015-10-29 09:54:15 ERROR StandardManager - Exception loading sessions from persistent storage
java.io.InvalidClassException: com.vaadin.server.WebBrowser; local class incompatible: stream classdesc serialVersionUID = -4707470459521903161, local class serialVersionUID = 1931594131304735556
        at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:621) ~[?:1.8.0_51]
        at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1623) ~[?:1.8.0_51]
        at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1518) ~[?:1.8.0_51]
        at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1774) ~[?:1.8.0_51]
        at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351) ~[?:1.8.0_51]
        at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2000) ~[?:1.8.0_51]
        at java.io.ObjectInputStream.defaultReadObject(ObjectInputStream.java:501) ~[?:1.8.0_51]
        at com.vaadin.server.VaadinSession.readObject(VaadinSession.java:1443) ~[vaadin-server-7.5.6.jar:?]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_51]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_51]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_51]
        at java.lang.reflect.Method.invoke(Method.java:497) ~[?:1.8.0_51]
        at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1017) ~[?:1.8.0_51]
        at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1900) ~[?:1.8.0_51]
        at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1801) ~[?:1.8.0_51]
        at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351) ~[?:1.8.0_51]
        at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371) ~[?:1.8.0_51]
        at org.apache.catalina.session.StandardSession.doReadObject(StandardSession.java:1634) ~[catalina.jar:8.0.24]
        at org.apache.catalina.session.StandardSession.readObjectData(StandardSession.java:1099) ~[catalina.jar:8.0.24]
        at org.apache.catalina.session.StandardManager.doLoad(StandardManager.java:261) ~[catalina.jar:8.0.24]
        at org.apache.catalina.session.StandardManager.load(StandardManager.java:180) ~[catalina.jar:8.0.24]
        at org.apache.catalina.session.StandardManager.startInternal(StandardManager.java:460) [catalina.jar:8.0.24]
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) [catalina.jar:8.0.24]
        at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5184) [catalina.jar:8.0.24]
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) [catalina.jar:8.0.24]
        at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:725) [catalina.jar:8.0.24]
        at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:701) [catalina.jar:8.0.24]
        at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:717) [catalina.jar:8.0.24]
        at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:945) [catalina.jar:8.0.24]
        at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1768) [catalina.jar:8.0.24]
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [?:1.8.0_51]
        at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:1.8.0_51]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [?:1.8.0_51]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [?:1.8.0_51]
        at java.lang.Thread.run(Thread.java:745) [?:1.8.0_51]

After second startup everything is fine - no errors. Actually I found a solution on SO - this is issue with Tomcat session persistence across restarts.

But I looked to WebBrowser code and actually there is no serialVersionUID variable even though this class implements Serializable. Of course it can work because this variable is generated using hash function. But here is first, small question: is it really correct or is it a kind of bug?

Main question:

Assuming Vaadin usage, how to prevent such exceptions? Should I disable Tomcat session persistence or should I search for some bug/problems in my code?

Community
  • 1
  • 1
jsosnowski
  • 1,560
  • 3
  • 26
  • 56

1 Answers1

1

Preface: this answer assumes that some of your classes that are serialized/persisted change between deployments.

I certainly remember scratching my head the first time I ran into this with Tomcat. Just like you, we allowed serialVersionUID to be auto-generated for our serialized classes as well, which is some kind of hash of the members of the class. Therefore, if these classes change in any way, the automatically generated serialVersionUIDs will change for them. Which is really what you want.

So to cut a long story short, the system is doing what it is supposed to be doing (not really a bug at all). The persisted, serialized versions of your objects don't match the classes in the new deployment -- and therefore you get an exception when attempting to deserialize them. Then they are consumed/discarded, which is why it works on the 2nd restart.

One somewhat brutal deployment strategy could be to destroy the work\Catalina\localhost\yourapplicationname directory under Tomcat before deploying the new war. Destroying the entire work directory would be an antisocial act if there are other applications running under Tomcat:)

Of course, you could attempt to add support for deserializing multiple "versions" of objects, but that would be very, very hard to maintain.

Code4aliving
  • 448
  • 6
  • 15