Details
-
Bug
-
Status: Closed
-
Resolution: Fixed
-
7.0.0 CE GA1, 7.0.0 DXP GA1, 7.0.X EE
-
7.0.x
-
Committed
-
1.5
-
4
Description
In case of having a tomcat cluster with session replication, java.lang.ClassNotFoundException is thrown during session replication of classes that are loaded by a OSGI classloader:
02-Jun-2017 11:02:36.254 SEVERE [Tribes-Task-Receiver-1] org.apache.catalina.ha.session.DeltaManager.messageReceived Manager [localhost#]: Unable to receive message through TCP channel java.lang.ClassNotFoundException: test.session.replication.MySessionData at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:348) at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:628) at org.apache.catalina.tribes.io.ReplicationStream.resolveClass(ReplicationStream.java:80)
Root cause of this issue: tomcat, during session replication, has to deserialize replicated object, but at tomcat level there is no access to OSGI classloaders, so a ClassNotFoundException exception is thrown.
This issue can be reproduced:
- From webcontent portlet This portlet is using com.liferay.petra.collection.stack.FiniteUniqueStack class that is loaded using a classloader from a OSGI module
- From a external portlet that stores custom class inside portlet session, see attached example test-session-replication-portlet.war
Environment setup
Configure Liferay cluster with two tomcat nodes, see instructions in ----LPS-72500
Steps to reproduce using web content functionality
- Start first tomcat node and wait until startup finish
- Verify you can login from browser using URL: http://localhost:8080/web/guest
- Start second tomcat node and wait until startup finish
- Review LIFERAY_HOME/tomcat-8.0.32/logs/cluster.2017-xx-xx.log files of both nodes (see configuration explained in ----
----) and verify that tomcat cluster is working.LPS-72500 - Login in any node of cluster
- Go to Control Panel => Web content section => create a new web content
- Check cluster log files:
- Correct behavior: No error is displayed
- Wrong behavior: Following error is displayed in some session event replication, in the opposite node
(if you create web content in first node, error is displayed in second one and vice-versa)02-Jun-2017 08:09:43.260 SEVERE [Tribes-Task-Receiver-2] org.apache.catalina.ha.session.DeltaManager.messageReceived Manager [localhost#]: Unable to receive message through TCP channel java.lang.ClassNotFoundException: com.liferay.petra.collection.stack.FiniteUniqueStack at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:348) at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:628) at org.apache.catalina.tribes.io.ReplicationStream.resolveClass(ReplicationStream.java:80) at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1620) at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1521) at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1781) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1353) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:373) at org.apache.catalina.ha.session.DeltaRequest$AttributeInfo.readExternal(DeltaRequest.java:387) at org.apache.catalina.ha.session.DeltaRequest.readExternal(DeltaRequest.java:277) at org.apache.catalina.ha.session.DeltaManager.deserializeDeltaRequest(DeltaManager.java:565) at org.apache.catalina.ha.session.DeltaManager.handleSESSION_DELTA(DeltaManager.java:1233)
- Correct behavior: No error is displayed
Steps to reproduce using 'test-session-replication-portlet.war'
- Start first tomcat node and wait until startup finish
- Verify you can login from browser using URL: http://localhost:8080/web/guest
- Install attached test-session-replication-portlet.war
in first tomcat node (copy war to liferay deploy directory)
- Create a page called "session replication test"
- Add test session replication portlet to created page
- Start second tomcat node and wait until startup finish
- Install attached test-session-replication-portlet.war
in second tomcat node (copy war to liferay deploy directory)
- Open created page "session replication test" in a new browser using URL of first node
- Following message will be displayed: No sessionData exists, generated a new one with random string ....
- Refresh page: generated random string will be displayed again
- In same browser, open same page but in second node.
- Correct behavior: Same random string generated in first node will be displayed in second one (random string is replicated through tomcat session replication)
- Wrong behavior: A new random string is generated again (random string is not replicated through tomcat session replication)
- Correct behavior: Same random string generated in first node will be displayed in second one (random string is replicated through tomcat session replication)
- Check cluster log files:
- Correct behavior: No error is displayed
- Wrong behavior: Following error is displayed in some session event replication, in the opposite node
02-Jun-2017 10:52:11.871 SEVERE [Tribes-Task-Receiver-6] org.apache.catalina.ha.session.DeltaManager.messageReceived Manager [localhost#]: Unable to receive message through TCP channel java.lang.ClassNotFoundException: test.session.replication.MySessionData at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:348) at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:628) at org.apache.catalina.tribes.io.ReplicationStream.resolveClass(ReplicationStream.java:80) at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1620) at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1521) at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1781) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1353) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:373) at org.apache.catalina.ha.session.DeltaRequest$AttributeInfo.readExternal(DeltaRequest.java:387) at org.apache.catalina.ha.session.DeltaRequest.readExternal(DeltaRequest.java:277) at org.apache.catalina.ha.session.DeltaManager.deserializeDeltaRequest(DeltaManager.java:565) at org.apache.catalina.ha.session.DeltaManager.handleSESSION_DELTA(DeltaManager.java:1233)
- Correct behavior: No error is displayed
If you install this test-session-replication-portlet.war
in Liferay 6.2 version, exception is not reproduced and generated random string is replicated from one node to other thought session.
For QA, after fix, you need to set "portlet.session.replicate.enabled=true" in portal-ext.properties and same steps as above to verify.
Attachments
Issue Links
- Discovered while testing
-
LPS-72500 java.lang.ClassNotFoundException: org.eclipse.equinox.http.servlet.internal.servlet.HttpSessionAdaptor$ParentSessionListener is thrown in case of having a tomcat cluster with session replication
- Closed
- is related to
-
LPS-135570 ClassNotFoundException is thrown during session replication while loading persisted sessions
- Closed
- relates
-
LPS-82509 Unable to find class when serialized objects are transfered between nodes with different versions even if class is compatible
- Closed
-
LPS-73732 In case of having a tomcat cluster with session replication, java.lang.ClassNotFoundException is thrown during startup or shutdown of one cluster node
- Closed