4

We have a scenario with a webapp implemented as a number of OSGi bundles. We want to do bundle updates to transparently deploy bugfixes etc to the running system. Assuming an update cycle with refresh and bundle restarts, this will cause problems when objects, whose classes are being reloaded, have been stored on the HttpSession leading to ClassCastExceptions.

We are looking at several different ways to make bundle updates possible without losing state in logged-in sessions. To simplify the session state access dependency graph we are thinking about setting the following restrictions:

  • a bundle can only access its own session state, i e no direct access to state set by another bundle (forces to instead call bundle API to indirectly access its state)
  • the Java classes of objects added to session state should come from the bundle itself (to avoid having our session state affected by updates of other bundles than ourselves) These restrictions are really only needed by some of the alternatives below.

So, these are the alternatives we have come up with in some kind of least to greatest implication order:

  1. Store all state as java.* types (String, List, etc)
    –> state classes are never subject to reloading.
  2. Lock sessions to the service versions its state was created with (by f ex using proxying solutions that forward to the version used earlier by that session)
    -> new sessions will pick up updated bundle versions while existing sessions will stay on the old versions.
  3. Serialize session state when updating a bundle and deserialize it back into the new bundle version (like appserver session serialization but on a more granular level)
    -> all sessions will pick up the updated bundles but requires that serialized state is compatible.
  4. Avoid updating stateful services as long as there are active sessions, making use of traditional load balancer techniques to update one appserver at a time
    -> longer deploy turnaround and may need more resources.
  5. Avoid stateful OSGi services altogether and keep state elsewhere
    -> not handling the problem in OSGi...

Did I miss any interesting alternatives?
What solutions do you recommend?

[although this post explicitly talks about session state the same discussion could apply to other scopes such as conversation state, application state, etc]

Community
  • 1
  • 1
mikewse
  • 457
  • 3
  • 11
  • What about keeping the actual objects stored in the sessions in their own bundle? Wouldn't that avoid the class cast exceptions? – ilikeorangutans May 06 '13 at 17:55
  • Yes, I was thinking of adding that as a separate alternative but I didn't as we still come back to the other alternatives if those bundles with "state classes" are updated. – mikewse May 06 '13 at 22:07

1 Answers1

4

In my opinion the right answer is not a simple rule but a set of rules like:

  • Use stateful objects only at the entry point of your application if necessary. Entry point can be the Servlet, socket listener, listener class of an IO device (something that sends request to your app from outside and needs state) ...
  • Store objects only in you session that are instantiated from classes coming from java.*; (Your first option.)
  • If you think you need to store a complex data structure think again. Is your motivation to return a persistent data faster?
  • Store as less information in the session as you can (no entity objects but only the id of them)
  • Use caches in the service bundles to speed up response time. I recommend using a key-value pair cache implementation that supports clustering, and XA transactions. Both requirements can be important later. In the keys use only java.* classes. In case of read intensive data usage (big percent in case of web applications) use invalidation cache.

More about caches and persistent data relationship:

  • Divide your persistent data to logical sets where one set has the same lifecycle.
  • One logical set of data can be modified and cached only from one bundle. If you do not have this rule cache can get corrupted if someone changes the code of one bundle (that would affect a cache in another bundle).

This is the way how we design web applications at my company and it seems to be the good way. However, there can be other ways.

Balazs Zsoldos
  • 6,036
  • 2
  • 23
  • 31