NotSerializable exception: PersonManagerImpl

3 min read >

NotSerializable exception: PersonManagerImpl

Engineering Insights & Enterprise solutions

I recently stumbled across a NotSerializableException in the project I was working on, and I decided to share this experience with you because the cause of the problem it’s quite interesting and some of you might come across the same problem.

First of all, the first thing noticed was that the exception was thrown when trying to serialize the HTTP servlet session. By some sort of “accident”, the session contained an object that was not serializable. So far everything seemed normal. The one thing that was weird about it was that the object in question was an instance of PersonManagerImpl. Let’s say that this is the name of one of the classes in our project. It’s a class that implements some business service interface, named PersonManager.

“Now, wait a minute!”, I said. “How the f*** did that come to be on the session?”

After a closer look, I noticed that the name of the offending class was not actually PersonManagerImpl, but PersonManagerImpl$1.
“A-ha!” That just made it a little easier for me. All I had to look for ways to find an anonymous inner class of PersonManagerImpl, and discover how it got to be put on the session.

After some digging in the code, I found the following lines (Note: these are not the actual names of classes and methods, but you get the point):

Get a set of persons by some criteria
Set<Person> persons = personDao.findSomePersons(someCriteria);
// Sort the set of persons by some criteria (because the DAO method returned an unsorted Set)
TreeSet sortedSet = new TreeSet(new Comparator<Person>() {
    public int compare(Person p1, Person o2) {
        return p1.getPosition().compareTo(p2.getPosition());
    }
});
sortedSet.addAll(persons);
session.setAttribute(SOME_PERSONS, sortedSet);

So, to make it all clear: what happened here was that the sorted set was saved as a session attribute, but along with it was also saved the Comparator, which was declared as an anonymous inner class of PersonManagerImpl.

To fix this annoying bug, the easy solution was to make the Person class implement Comparable:

lic class Person implements Serializable, Comparable {
    .......
public int compareTo(Object o) {
Person that = (Person) o;
return this.position.compareTo(that.position);
}
}

and change the sorting code to:

sortedSet = new TreeSet();
sortedSet.addAll(persons);