Java Object serialization API provides a framework for encoding objects as byte streams and reconstructing objects from their byte-stream encodings.
MGNLUI-351 - Getting issue details... STATUS
As explained in the issue above, Magnolia is currently unable to serialise and deserialise its own Admicentral UI. This may be a problem especially in clustered environments where a user session may need to be replicated across multiple Java VMs.
In Magnolia's case the root object being serialised when a servlet container shuts down is
VaadinSession which is a
Serializable class. Most Vaadin classes are serializable, including
UI from which our
AdmincentralUI inherits. This sort of forces us to take care of serialization in our own classes.
We want to detect and remove all serialisation issues in our code.
Furthermore, we want to find a way to detect serialization issues during Magnolia build so that they are caught and tackled early.
Downsides of Serialisation
Before proceeding with a possible solution I came up during my investigations and trials I'd like to point out some of the not so negligible disadvantages Serialization entails.
The points are mostly taken from Effective Java, 2nd Edition by Joshua Bloch which begins his chapter on Serialization with this significant warning: implement Serializable judiciously.
Implementing Serializable decreases the flexibility to change a class’s implementation once it has been released.
"When a class implements Serializable, its byte-stream encoding (or serialized form) becomes part of its exported API. Once you distribute a class widely, you are generally required to support the serialized form forever, just as you are required to support all other parts of the exported API. If you do not make the effort to design a custom serialised form, but merely accept the default, the serialised form will forever be tied to the class’s original internal representation."
Increases the testing burden associated with releasing a new version of a class
"When a serializable class is revised, it is important to check that it is possible to serialise an instance in the new release and deserialise it in old releases, and vice versa. [...] These tests cannot be constructed automatically because, in addition to binary compatibility, you must test for semantic compatibility. In other words, you must ensure both that the serialization-deserialization process succeeds and that it results in a faithful replica of the original object."
It can consume excessive space
Especially using the default serialization mechanism you might end up with a huge object graph of painstakingly and recursively mirror every field and/or entry in a Collection.
It can consume excessive time
The serialization logic has no knowledge of the topology of the object graph, so it must go through an expensive graph traversal.
Detecting and removing serialization issues
After several attempts (which will be mentioned later on), this is the approach I would suggest
- start tomcat with this JVM parameter
- login into Magnolia
- stop and restart Magnolia
- in the logs something like the following stack trace will show up
- With this information try to fix the "offending" class.
- In the case above, an inner class of
ResettableEventBusseems to be not serialisable. It is interesting to notice how the root object being serialised is a
VaadinSession. Thanks to the
extendedDebugInfoyou can follow up the whole serialisation path in the object graph until it throws a
Unfortunately the report provided by
extendedDebugInfo is not a full one, meaning that it stops at the first error encountered. This means your only option is to fix and start over the process outlined above until no more serialization exceptions show up.
Before giving up to the laborious manual process above, I tried several options, including some fancy recursive scripts through the whole object graph using reflections and other magic. But to no avail. You can read about them in my comment to JIRA issue.
Use default serialization mechanism sparingly
In the first attempt I tried, I basically made each problematic class implement Serializable and let Java do the job. This soon turned out into having a gigantic object graph to be serialised where even Magnolia's core classes came into the picture. Consider the following example.
Finding a way to detect serialization issues during Magnolia build
In this case I came up with a very simple Groovy script
This works fine when run through the Magnolia Groovy Console and will basically output the same stack trace by Tomcat. I thought it could be run as an integration test, like we do for our
crawler.groovy. However this does not work, the Groovy Maven plugin being basically disconnected from the Magnolia test instance (two different threads).
Find a way to run the script above as an integration test against a real Magnolia instance. One idea could be registering a GroovyTestServlet which will get passed the script source and executes it. Then we assert that the output does not contain
What to serialize
While trying to remove all serialization errors, to my dismay I realised there are much more classes needing to be serialised than what I expected. Also Magnolia core classes come into play and I start wondering what should actually be serialised, what fields be made
transient and how to effectively serialise and deserialise the
VaadinSession without going and making everything