5

Let's say we have a web application backed by a servlet engine/container like Tomcat. A user logs in. The database record for that user (represented by an instance of class User, let's say) is loaded, and we can store this as a session attribute with the key "currentUser", set it once, and use it to handle subsequent requests. In addition, we put more objects in the session attribute. Pretty basic stuff.

Now, if we need to deploy some new code and reboot Tomcat... The user sessions are still intact after reboot (restored from disk/db) as long as we don't change any of the classes whose instances are stored in the user session. But this is a big problem. I don't want users losing their sessions on new code release.

To get around this problem, I suppose that I can store in the session object only instances of classes that are assumed to not ever change (like storing the logged-in user's ID as an Integer as opposed to an instance of the User class). Then I'd never run into a problem of not being able to deserialize the session object upon reboot. But this makes things slightly more complicated as now I have to use the ID to load the actual object from the database, etc (and with caching, performance hit is not really an issue).

Is this what's typically done to get around this issue?

n00b
  • 167
  • 1
  • 2
  • 8
  • the 1st scenario (storing full blown objects) requires a bit of time investment to understand how serialization works. If done properly you should never "lose" anything on a new release. – bestsss May 11 '11 at 22:25

3 Answers3

3

Simple Solution

as you suggested, load only the userId in your session, and use cache service such as ehcache to retrieve user objects. If the user object does not exist, it will be loaded the first time but then it will be cached and subsequent requests will pretty fast. If you are concerned about your user class changes, make your cache memory based only so it will reset between server reboots.

Platform solution

Take a look at Terracotta (http://www.terracotta.org/). If you are able to deploy your sessions on their platform, they will allow you to maintain them between server reboots as well as update the actual user class while keeping old fields. Pretty cool things once you have it up and running.

Keep in mind though that Terracotta integration is not simple and not for novices. The benefits however are scalability and high availability that all web applications require in general.

Pierre
  • 1,329
  • 2
  • 12
  • 21
  • This is exactly what I ended up doing. I just changed the implementation of the wrapper function for getting/setting user info. I use Spring/Hibernate so turning on EhCache was a breeze. Thanks for the info on Terracotta. – n00b May 13 '11 at 21:28
2

As far as serialization goes, provided you do not change serialization format it won't be a problem. Otherwise you'll get the dreaded InvalidClassException. What you'll need to do is:

  1. Set a serialVersionUID on every object you are serializing: provided you don't drastically change the fields on the class between reboots this should be sufficient.
  2. Override the writeObject/readObject methods to precisely control the serialization format: if you do this you can even work around drastic changes in the class.
  3. Use JSON/XML or any other storage format that cleanly handles translation. Perhaps your best bet.
Femi
  • 64,273
  • 8
  • 118
  • 148
1

Interesting situation and nice question.

Typically, from what I have seen in enterprise environments, sessions are usually killed after a new version of the web application is deployed - since it's a new deployment anyway, the application server usually doesn't know the difference between a new app and a new version. I don't think it would be a good idea if the servers keep the sessions, since it may just be a completely different application, to which the user may not have any access permissions etc, so this might be a security issue.

However, let's assume the sessions would be persisted and could be restored even for new deployments. The way you describe sounds just about right, you could as well do it a bit more sophisticated, such as checking whether the session has old objects which need to be converted (or loaded from the database again) based on their version. In Java, you would try hard to have your classes be binary compatible, so the new version of the application can still deserialize it. That's what writeObject/readObject are for.

Another idea is to store the 'session' in your own data format in the database and have the session only for lightweight data, such as user authentication and your own application session id. I've never seen that in a Java application though, but it makes it possible to do what you want and perform migration steps at deployment time for migrating the data to the new format. Together with auto-login/remember-me cookies, your users would not see any difference.

mhaller
  • 14,122
  • 1
  • 42
  • 61