[MGNLUI-351] UI classes persisted in session not serializable Created: 06/Dec/12  Updated: 28/Mar/17  Resolved: 07/Jul/16

Status: Closed
Project: Magnolia UI
Component/s: None
Affects Version/s: 5.0
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Jan Haderka Assignee: Federico Grilli
Resolution: Won't Fix Votes: 5
Labels: framework, support
Remaining Estimate: 0d
Time Spent: 2.75d
Original Estimate: Not Specified

Attachments: Text File stacktrace.txt    
Issue Links:
causality
duplicate
is duplicated by MGNLUI-2477 Not Serializable Exception Closed
relation
is related to MGNLUI-2652 Serialisation issue with Admincentral... Closed
is related to MGNLUI-2477 Not Serializable Exception Closed
is related to MAGNOLIA-5321 NotSeriazableException with Magnolia ... Closed
is related to MGNLCE-46 Disable session persistence on tomcat... Closed
is related to MGNLEE-444 Disable session persistence on tomcat... Closed
Template:
Acceptance criteria:
Empty
Task DoD:
[ ]* Doc/release notes changes? Comment present?
[ ]* Downstream builds green?
[ ]* Solution information and context easily available?
[ ]* Tests
[ ]* FixVersion filled and not yet released
[ ]  Architecture Decision Record (ADR)
Bug DoR:
[ ]* Steps to reproduce, expected, and actual results filled
[ ]* Affected version filled
Date of First Response:
Story Points: 13

 Description   

see MGNLUI-2477 for details. But I'm pretty sure there's more classes affected. Fix for the issue should include change in pom or hudson build for UI to systematically check and ensure all ui classes that might eventually end up in session are serializable. Otherwise this bug will resurface soon again and again.

OUTCOME
The results of the time boxed investigation are summarised at https://wiki.magnolia-cms.com/display/DEV/Serialization+issues

ARCH Meeting
Based on the results of the investigation done in the past few days it has been decided to postpone support for session serialization after Magnolia 5.5. Magnolia Tomcat bundle will come with session persistence disabled as of versions 5.4.8 and 5.5.
Documentation will follow on how to disable it for other containers (DOCU-751).



 Comments   
Comment by joshua portway [ 08/Jan/14 ]

I think this is probably the problem I'm having running 5.2.1 on JBoss. I get literally hundreds of these exceptions flying past all the time (I presume one per request) :

02:04:57,231 WARNING [com.vaadin.event.ListenerMethod] (http-localhost/127.0.0.1:8080-1) Error in serialization of the application: Class info.magnolia.ui.admincentral.AdmincentralVaadinServlet$1$1 must implement serialization.
02:04:57,249 ERROR [org.infinispan.interceptors.InvocationContextInterceptor] (http-localhost/127.0.0.1:8080-1) ISPN000136: Execution error: org.infinispan.marshall.NotSerializableException: org.jboss.modules.ModuleClassLoader
Caused by: an exception which occurred:
	in field classLoader
	in field servletService
	in field this$0
	in field this$1
	in field target
	in field listenerList
	in field eventRouter
	in object java.util.HashMap@88524b0b
	in object org.jboss.as.clustering.SimpleMarshalledValue@88524b0b
	in object org.infinispan.util.FastCopyHashMap@13fc785e
	in object org.infinispan.atomic.AtomicHashMap@30878ff6
	in object org.infinispan.container.entries.ImmortalCacheEntry@da7cc371
	in object org.infinispan.loaders.bucket.Bucket@23e5f056

02:04:57,250 ERROR [org.infinispan.transaction.TransactionCoordinator] (http-localhost/127.0.0.1:8080-1) ISPN000188: Error while processing a commit in a two-phase transaction: org.infinispan.marshall.NotSerializableException: org.jboss.modules.ModuleClassLoader
Caused by: an exception which occurred:
	in field classLoader
	in field servletService
	in field this$0
	in field this$1
	in field target
	in field listenerList
	in field eventRouter
	in object java.util.HashMap@88524b0b
	in object org.jboss.as.clustering.SimpleMarshalledValue@88524b0b
	in object org.infinispan.util.FastCopyHashMap@13fc785e
	in object org.infinispan.atomic.AtomicHashMap@30878ff6
	in object org.infinispan.container.entries.ImmortalCacheEntry@da7cc371
	in object org.infinispan.loaders.bucket.Bucket@23e5f056

02:04:57,250 ERROR [org.infinispan.transaction.tm.DummyTransaction] (http-localhost/127.0.0.1:8080-1) ISPN000111: afterCompletion() failed for SynchronizationAdapter{localTransaction=LocalTransaction{remoteLockedNodes=null, isMarkedForRollback=false, lockedKeys=null, backupKeyLocks=null, topologyId=-1, isFromStateTransfer=false} org.infinispan.transaction.synchronization.SyncLocalTransaction@6d} org.infinispan.transaction.synchronization.SynchronizationAdapter@8c: org.infinispan.CacheException: Could not commit.
	at org.infinispan.transaction.synchronization.SynchronizationAdapter.afterCompletion(SynchronizationAdapter.java:83)
	at org.infinispan.transaction.tm.DummyTransaction.notifyAfterCompletion(DummyTransaction.java:285)
	at org.infinispan.transaction.tm.DummyTransaction.runCommitTx(DummyTransaction.java:334)
	at org.infinispan.transaction.tm.DummyTransaction.commit(DummyTransaction.java:91)
	at org.infinispan.transaction.tm.DummyBaseTransactionManager.commit(DummyBaseTransactionManager.java:102)
	at org.jboss.as.clustering.web.impl.TransactionBatchingManager.endBatch(TransactionBatchingManager.java:75)
	at org.jboss.as.web.session.DistributableSessionManager.processSessionRepl(DistributableSessionManager.java:1571) [jboss-as-web-7.3.0.Final-redhat-14.jar:7.3.0.Final-redhat-14]
	at org.jboss.as.web.session.DistributableSessionManager.storeSession(DistributableSessionManager.java:872) [jboss-as-web-7.3.0.Final-redhat-14.jar:7.3.0.Final-redhat-14]
	at org.jboss.as.web.session.InstantSnapshotManager.snapshot(InstantSnapshotManager.java:47) [jboss-as-web-7.3.0.Final-redhat-14.jar:7.3.0.Final-redhat-14]
	at org.jboss.as.web.session.ClusteredSessionValve.handleRequest(ClusteredSessionValve.java:142) [jboss-as-web-7.3.0.Final-redhat-14.jar:7.3.0.Final-redhat-14]
	at org.jboss.as.web.session.ClusteredSessionValve.invoke(ClusteredSessionValve.java:99) [jboss-as-web-7.3.0.Final-redhat-14.jar:7.3.0.Final-redhat-14]
	at org.jboss.as.web.session.JvmRouteValve.invoke(JvmRouteValve.java:92) [jboss-as-web-7.3.0.Final-redhat-14.jar:7.3.0.Final-redhat-14]
	at org.jboss.as.web.session.LockingValve.invoke(LockingValve.java:64) [jboss-as-web-7.3.0.Final-redhat-14.jar:7.3.0.Final-redhat-14]
	at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:169) [jboss-as-web-7.3.0.Final-redhat-14.jar:7.3.0.Final-redhat-14]
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:145) [jbossweb-7.2.2.Final-redhat-1.jar:7.2.2.Final-redhat-1]
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:97) [jbossweb-7.2.2.Final-redhat-1.jar:7.2.2.Final-redhat-1]
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:102) [jbossweb-7.2.2.Final-redhat-1.jar:7.2.2.Final-redhat-1]
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:336) [jbossweb-7.2.2.Final-redhat-1.jar:7.2.2.Final-redhat-1]
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:856) [jbossweb-7.2.2.Final-redhat-1.jar:7.2.2.Final-redhat-1]
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:653) [jbossweb-7.2.2.Final-redhat-1.jar:7.2.2.Final-redhat-1]
	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:920) [jbossweb-7.2.2.Final-redhat-1.jar:7.2.2.Final-redhat-1]
	at java.lang.Thread.run(Thread.java:744) [rt.jar:1.7.0_45]
Caused by: javax.transaction.xa.XAException
	at org.infinispan.transaction.TransactionCoordinator.handleCommitFailure(TransactionCoordinator.java:224)
	at org.infinispan.transaction.TransactionCoordinator.commit(TransactionCoordinator.java:185)
	at org.infinispan.transaction.synchronization.SynchronizationAdapter.afterCompletion(SynchronizationAdapter.java:81)
	... 21 more

Comment by Jan Haderka [ 03/Sep/14 ]

Necessary code changes are now in branches. Tested only for Pages and Config apps, so there might be more.
The code is more to be used as a base for discussion rather then fix.

Following questions are the ones I can think of right now:

  • How to test to prevent this from happening? I can imagine only integration test that starts Magnolia, opens all available apps (and perhaps performs some extra functions in those apps), shutdown the server, start it up again and looks for NSE in logs. This seems to be quite heavy, thus not really desirable.
  • As you can see from the branches, at the moment it's not anymore only UI affected, but number of core classes too. Doesn't seem like good option to force serialisation support on core classes as well, so we might want to think about dereferencing all the stuff in UI instead.
  • Some changes were necessary to guice impl. Namely declaring Injector transient. While various sources on the net claim that to be safe, and it is similar to approach taken by wicket-guice integration, it doesn't feel safe w/o more tests.
  • There are still 3 classes that have variables that have somewhere down the road reference to InjectorImpl$4. Those classes are: info.magnolia.ui.framework.message.LocalMessageDispatcher, info.magnolia.ui.framework.task.LocalTaskDispatcherManager, info.magnolia.ui.framework.shell.ShellImpl. As additional hint I can offer is that the reference is coming through something stored in ArrayListMultimap.
Comment by Aleksandr Pchelintcev [ 03/Sep/14 ]

@Jan: Regarding point 4 - I guess those "holders in ArrayListMultimap" would be the event handlers that have a reference to a component provider in their impl.

Comment by Jan Haderka [ 03/Sep/14 ]

@Sasha: yeah, that is my guess too. But after 6 hours spent figuring out all the other things there, I don't see anything obvious in the provider nor in any of the handlers. Maybe in couple of days, or maybe someone else is luckier than me in the mean time

Comment by Jan Haderka [ 10/Sep/14 ]

Similar stack trace from tomcat showing that instance of object referenced by variable in VaadinListener holds reference to web app class loader. Adding debug log (or breakpoint) to com.vaadin.event.ListenerMethod.writeObject(ListenerMethod.java:88) shows the object in question on shutdown of App server.

Comment by Dominika [ 27/Oct/14 ]

This might be a big problem for those users who decide to persist sessions in REDIS (for example). At the moment it is impossible to run Magnolia:

Oct 27, 2014 12:45:02 AM com.radiadesign.catalina.session.RedisSessionManager loadSessionFromRedis
SEVERE: writing aborted; java.io.NotSerializableException: org.apache.catalina.loader.WebappClassLoader
	- field (class "com.vaadin.server.VaadinService", name: "classLoader", type: "class java.lang.ClassLoader")
	- object (class "info.magnolia.ui.admincentral.AdmincentralVaadinServlet$2", info.magnolia.ui.admincentral.AdmincentralVaadinServlet$2@1d6c95cb)
	- field (class "com.vaadin.server.VaadinServlet", name: "servletService", type: "class com.vaadin.server.VaadinServletService")
	- object (class "info.magnolia.ui.admincentral.AdmincentralVaadinServlet", info.magnolia.ui.admincentral.AdmincentralVaadinServlet@2fb52475)
	- field (class "info.magnolia.ui.admincentral.AdmincentralVaadinServlet$1", name: "this$0", type: "class info.magnolia.ui.admincentral.AdmincentralVaadinServlet")
	- object (class "info.magnolia.ui.admincentral.AdmincentralVaadinServlet$1", info.magnolia.ui.admincentral.AdmincentralVaadinServlet$1@3823bca7)
	- field (class "info.magnolia.ui.admincentral.AdmincentralVaadinServlet$1$1", name: "this$1", type: "class info.magnolia.ui.admincentral.AdmincentralVaadinServlet$1")
	- object (class "info.magnolia.ui.admincentral.AdmincentralVaadinServlet$1$1", info.magnolia.ui.admincentral.AdmincentralVaadinServlet$1$1@44760259)
	- field (class "com.vaadin.event.ListenerMethod", name: "target", type: "class java.lang.Object")
	- custom writeObject data (class "com.vaadin.event.ListenerMethod")
	- object (class "com.vaadin.event.ListenerMethod", com.vaadin.event.ListenerMethod@86bde733)
	- custom writeObject data (class "java.util.HashSet")
	- object (class "java.util.LinkedHashSet", [com.vaadin.event.ListenerMethod@86bde733, com.vaadin.event.ListenerMethod@21cd63a0])
	- field (class "com.vaadin.event.EventRouter", name: "listenerList", type: "class java.util.LinkedHashSet")
	- object (class "com.vaadin.event.EventRouter", com.vaadin.event.EventRouter@2b45d06a)
	- field (class "com.vaadin.server.VaadinSession", name: "eventRouter", type: "class com.vaadin.event.EventRouter")
	- root object (class "com.vaadin.server.VaadinSession", com.vaadin.server.VaadinSession@29940134)

This is very similar to Vaadin issue [#http://dev.vaadin.com/ticket/8644].

Its Magnolia we can't use with Redis, but I think that the issues fully relate to Vaadin:
1. com.vaadin.server.VaadinService should not reference classLoader.
2. com.vaadin.server.VaadinSession should not serialize (maybe have transient?) eventRouter as it references - and will serialize - servlets.

EDIT:

I have SOLVED the problem! By further looking at the stacktrace I looked closed into eventRouter property. To add a listener the method addBootstrapListener must be called. I found it in:

AdmincentralVaadinServlet.java
 103                  event.getSession().addBootstrapListener(new BootstrapListener() {
 104 
 105                     @Override
 106                     public void modifyBootstrapPage(BootstrapPageResponse response) {
 107                         response.getDocument().head().append("<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no\" />");
 108                     }
 109 
 110                     @Override
 111                     public void modifyBootstrapFragment(BootstrapFragmentResponse response) {
 112                     }
 113                 });

I moved inner BootstrapListener to a separate class, to get rid of serialization of this$1 and this$0.

And it worked like a charm!

AdmincentralVaadinServlet.java
 103                  event.getSession().addBootstrapListener(new AdmincentralVaadinServletSessionInitListener());
AdmincentralVaadinServletSessionInitListener.java
package info.magnolia.ui.admincentral;

import com.vaadin.server.BootstrapFragmentResponse;
import com.vaadin.server.BootstrapListener;
import com.vaadin.server.BootstrapPageResponse;
/**
 * The AdmincentralVaadinServletSessionInitListener.
 */
@SuppressWarnings("serial")
public class AdmincentralVaadinServletSessionInitListener implements BootstrapListener {

    /**
     * Implementation.
     */
    @Override
    public void modifyBootstrapPage(BootstrapPageResponse response) {
        response.getDocument().head().append("<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no\" />");
    }

    /**
     * Implementation.
     */
    @Override
    public void modifyBootstrapFragment(BootstrapFragmentResponse response) {
    }
}

Now I need to deal with another issue:

Oct 27, 2014 2:52:17 AM org.apache.catalina.session.StandardSession writeObject
WARNING: Cannot serialize session attribute com.vaadin.server.VaadinSession.AdminCentral for session C7B62093614C313819CFFE640487B1C0
java.io.NotSerializableException: info.magnolia.init.DefaultMagnoliaConfigurationProperties
	- field (class "info.magnolia.ui.admincentral.AdmincentralUIProvider", name: "magnoliaProperties", type: "interface info.magnolia.init.MagnoliaConfigurationProperties")
	- object (class "info.magnolia.ui.admincentral.AdmincentralUIProvider", info.magnolia.ui.admincentral.AdmincentralUIProvider@324c068e)
	- custom writeObject data (class "java.util.LinkedList")
	- object (class "java.util.LinkedList", [info.magnolia.ui.admincentral.AdmincentralUIProvider@324c068e, com.vaadin.server.DefaultUIProvider@1d426e6e])
	- field (class "com.vaadin.server.VaadinSession", name: "uiProviders", type: "class java.util.LinkedList")
	- root object (class "com.vaadin.server.VaadinSession", com.vaadin.server.VaadinSession@8981cae)
Comment by Jan Haderka [ 07/Jul/16 ]

Serialization of sessions and/or transfer of sessions is currently not supported by Magnolia. This problem will be revisited once full support for clustering is being implemented. Until then, it is recommended to disable session persistence as shown in MGNLCE-46 or MGNLEE-444.

Comment by Michiel Meeuwissen [ 28/Mar/17 ]

I would have liked to serialize the vaadin session too, because we have problems with very slow admin interfaces, seemingly related to vaadin sesion. Sadly, because of this bug, it is not possible now?

Generated at Mon Feb 12 08:36:01 CET 2024 using Jira 9.4.2#940002-sha1:46d1a51de284217efdcb32434eab47a99af2938b.