Skip to content

2.5. Serializing Session Objects

This chapter states the one condition placed on application code.

While the session lived in WAS memory, objects could be left as they were; sending them to the data grid requires converting them to bytes. Objects placed in the session must therefore implement Serializable. Storing an object that does not implement it raises an error at the moment it is saved.

To place a User object in the session as shown below, the User class must implement Serializable.

User user = new User();
...
session.setAttribute("key", user);
public class User implements Serializable {

}

Four Things to Check

First, the objects held inside must be serializable too. If User has an Address field, Address must also be Serializable. If even one is not, saving raises java.io.NotSerializableException, and the exception message names the offending class.

Second, mark fields that do not need to be stored as transient. Things that cannot be serialized — such as database connections and file handles — and values that can be recreated should be marked transient to exclude them from storage.

public class User implements Serializable {
private String userId;
private transient Connection conn; // not stored
}

Third, declare serialVersionUID. See "Keeping Sessions Intact Across Upgrades" below.

Fourth, do not put large objects in the session. The session travels to and from the store on every request, so the larger the objects it holds, the more network and conversion time it takes. Large data such as query result lists is better left out of the session and queried again when needed. You can check how large the session currently is with "Viewing Session Memory Usage".

Keeping Sessions Intact Across Upgrades

Declare serialVersionUID explicitly in every class you place in the session. Without it, upgrading the application to a new version can make all logged-in users hit errors at once.

Why It Is a Problem

serialVersionUID is the value used to check that serialized data and a class match. If you do not declare it, Java computes it automatically from the class structure — field names and types, methods, and implemented interfaces all go into the calculation.

As a result, even a small change to the class changes the value. Adding one field or renaming one produces a new value.

Sessions live on in the data grid outside the WAS. So even after you deploy a new version of the application, sessions stored by the previous version are still in the store. When the new code tries to read them, the values do not match and the read fails.

java.io.InvalidClassException: com.example.User; local class incompatible:
stream classdesc serialVersionUID = 8721905643012, local class serialVersionUID = 3390274612885

When It Shows Up

SituationWhat happens
During a zero-downtime deploymentWhile old-version and new-version instances run together, neither can read sessions stored by the other
After the deployment finishesErrors continue until the older sessions left in the store expire by timeout
On rollbackThe old version cannot read sessions stored by the new version, and the same problem repeats

This problem did not show up when only WAS memory was used. A restart removed the sessions along with it, so no old data remained. It is a new condition introduced by storing sessions outside.

What to Do

Write the value explicitly in every class you place in the session. The value itself can be anything; the point is not to change it when you modify the class.

public class User implements Serializable {
private static final long serialVersionUID = 1L;

private String userId;
private String name;
}

The same applies to objects held inside. If User has an Address, declare it in Address as well.

Changes That Are Unsafe Even With a Fixed Value

With serialVersionUID fixed, adding a field is safe. Older sessions do not have that field, so it is read as the default (null, 0, false).

The following, on the other hand, cause errors or misread values even with the value fixed.

  • Changing a field's type (StringLong, for example)
  • Deleting a field (it is ignored on read, but if code used that value, behavior changes)
  • Renaming the class or package

If you need such a change, clear the sessions in the store before deploying, or deploy at a quiet time to reduce the number of users who have to log in again.