Pivotal Knowledge Base

Follow

Tomcat session replication fails with the log entry: java.io.InvalidClassException (2010516)

Tomcat session replication fails with the log entry: java.io.InvalidClassException (2010516)

Symptoms

  • In a Tomcat cluster with session replication implemented and sticky sessions enabled at the load balancer, sessions persist during normal operations, but when failing over from one node to another, sessions are not found for requests redirected to the backup node, resulting in a new sessions being issued for these requests.

  • In the Tomcat server logs for the backup node, you see observe errors similar to: 

    Note: These errors occur if you are clustering with the DeltaManager, but they are similar if you are using BackupManager):

    • SEVERE org.apache.catalina.ha.session.DeltaManager.messageReceived Manager [localhost#/app]:
      Unable to receive message through TCP channel
      java.io.InvalidClassException: com.example.MyClass; no valid constructor

      Or:

    • SEVERE org.apache.catalina.ha.session.DeltaManager.deserializeSessions
      IOException while loading persisted sessions:
      java.io.InvalidClassException: com.example.MyClass; no valid constructor

Cause

When sessions are replicated between cluster nodes, they must be serialized by the sender and deserialized by the receiver. These errors indicate that the application has placed a Java object in the session (in this example, com.example.MyClass), which implements Serializable, but cannot be properly deserialized because of a non-serializable superclass in its class hierarchy.
 
The object in question is serialized successfully for sending, but java.io.InvalidClassException occurs when deserializing on the receiving (backup) node. The first error in the Symptoms indicates that this occurred while replicating a single session, in which case only that session becomes invalid. The second error in the Symptoms occurs when a node that is starting up receives a session state transfer from an existing node. In this case, deserialization is aborted for the entire transfer, so the node replicates only the sessions seen prior to raising this error.
 
For more information, see the Serializable javadocs.

Resolution

This issue can only be resolved by the application developer.
 
The class (com.example.MyClass in this example) should be made to implement Serializable fully. This means either:
  • All superclasses of the object's class (except Object) must be made to implement Serializable

    Or

  • The first superclass of the object's class that does not implement Serializable must be given a no-arg constructor that is accessible to the class (that is, not private). That class's subclass may need modification to implement serialization and deserialization of its attributes if necessary, using the writeObject and readObject methods described in the Serializable javadocs.

While it is necessary to implement Serializable correctly to include objects of the class in replicated sessions, the developer should evaluate the code and design of this class to ensure serialization and deserialization can be implemented correctly without causing problems. If this is difficult, the developer may also want to consider whether objects of this type should be placed in the session, or if the app can be redesigned to remove the need.

Additional Information

The logs supply further context for the errors if you add the this to your server logging properties:

Caution:  These logs are verbose and may impact server performance.
 
org.apache.catalina.ha.level = FINEST

The server will log a message with the session ID that is being loaded or replicated just before this error is experienced, which is the one containing the problem object. The server will also log messages for each session replication message and when sessions from another node are requested.

Confidential or Internal Solution information

Summarizes the issue in case 11123665912.

Good presentation of relevant code: http://grepcode.com/file/repository.springsource.com/org.apache.catalina/com.springsource.org.apache.catalina.ha/6.0.24/org/apache/catalina/ha/session/DeltaManager.java#DeltaManager.deserializeSessions%28byte[]%29

Server version in case was TC 6.0.29, but code doesn't look to have change much between 6.0.24 and 7.0.15.

See Also

©VMware 2013

Comments

Powered by Zendesk