These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 posts ] 
Author Message
 Post subject: Ajax and Long Sessions. How to evict free pojos?
PostPosted: Fri May 11, 2007 3:44 am 
Newbie

Joined: Tue Aug 08, 2006 3:53 am
Posts: 17
Location: Tanznaia
All,

So I'm building an interactive Webapp. The Ajax architecture encourages us to retrieve smaller chunks of data from the server but more frequently. In terms of frequency of client/server toing and froing, Ajax apps represent a mid point between traditional document-based web apps and fully interactive client/server applications.

With that in mind, it surprises me that my problem hasn't caused more noise. I am using Hibernate together with ZK (an Ajax framework) and have happily implemented the openSessionInView pattern.

However, a Hibernate session is not just a Database connection; it's also a first level cache. It means you can make multiple queries for the same object without breaking java equality (obj1==obj2).

As I said at the top, ZK (or rather Ajax) encourages you to dip back to the server more frequently, and I find myself manipulating the domain level objects incrementally. For example, the user clicks on a button and the name field of the domain object is updated which notified it's observers and updates the UI. Then The user clicks on the 'attach sub object' button which goes back to that same domain object and adds another object to a list.

Do you see my issue here? I'm holding a reference to this Domain Object (pojo) between request cycles. So my openSessionInView pattern is giving me a shiny new Hibernate session each time, empty of any cached references. So I end up with multiple versions of the same object that really are the same [obj1.getId()==obj2.getId()] but break java equality [obj1!=obj2]. This causes all sorts of unpleasant bugs.

So I dug around and finally found another, less well documented Hibernate pattern called 'sessionPerConversation.' (Thanks to this forum!) Basically, you keep the Hibernate session alive between request cycles with all it's lovely cache intact, but disconnect and reconnect the underlying database connection each time. You get no more double references, no more LazyInitialisation exceptions on my lazy collections and no more NonUniqueObject errors. It works like a charm.

I can think of one obvious downside to this which is memoryhogging. This session cache is likely to get large - especially if there is no easy way to clean it out before the end of that user's login session. So this leads to my question:

Does anyone know how I might tie into my POJOs so that, when there are no other references to it, I can evict it from the cache?

Is there something in Hibernate or CGLib that can do this? I know reference counting in terribly old school, but something similar would be very handy here. That way we can have a nice dynamic memory management solution.

It seems to me that with a little more engineering, this 'sessionPerConversation' should be the default for ajax/hibernate applications. It frees up the developer considerably as you can store POJO's wherever you like and use Lazy Initialisation to your hearts content.

I welcome any and all comments,

Regards,

Ben.


Top
 Profile  
 
 Post subject:
PostPosted: Fri May 11, 2007 4:19 am 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
This is exactly what http://www.jboss.com/products/seam does.

_________________
JAVA PERSISTENCE WITH HIBERNATE
http://jpwh.org
Get the book, training, and consulting for your Hibernate team.


Top
 Profile  
 
 Post subject: Hibernate Session Cache and Garbage Collection
PostPosted: Tue May 15, 2007 2:48 am 
Newbie

Joined: Tue Aug 08, 2006 3:53 am
Posts: 17
Location: Tanznaia
All,

If you've read the previous part of this thread you'll know I'm using long-lived sessions (to preserve the first level cache) and demarking transactions at each http request cycle. It's an AJAX webapp, so I'm incrementally changing the data and need this long-lived session cache so that my pojos can use java equality for their references, lazy loaded collections and cascade-loaded sub objects.

The solution works wonderfully (sessionPerConversation) and I'd like to write it up for the public domain. However, there is the issue of the session cache becoming bloated over time. You can explicitly evict objects when you're done with them of course, but once you leave the realm of 'one session per fuction' - it's very hard to know when that object is no longer required.

What I would like to do is to utilise the Java Garbage Collection mechanism to do this. I looked into the code and it's surprisingly simple to change - but required forking the Hibernate source as I can't add this behaviour by extension (as far as I can see).

I've been looking particularly into the source for the Session Cache (the StatefulPersistantContext class) and I'm a little disapointed that it's declared final so that I can't extend it's behavior.

Anyway, Here's my plan...

Inside the stateful cache, pojos are stored in a couple of Map collections, indexed in different ways. This is fine. All I need to do is to change these maps to store WeakReferences to the object instead. WeakReference is an intermediary class that will not be counted as a propper reference by the Garbage Collector when it needs to reclaim some heap. This way, as soon as the pojo is not reachable any other way than through the session cache (or any other weak references), the heap can be reclaimed and the pojo can be evicted. Probably the simplest thing would be to implement a [i]WeakReferenceHashMap[/b] that wraps and unwraps the pojos for you (and responds correctly when the weak references get reclaimed) and just change the classes that are created inside PersistantContext. The rest of the code could then remain the same.

Really, this is a very small change and one with huge benefits. You no longer need to worry about keeping you session object slim! Sure, if you're loading thousands of pojos at the same time, that'd still be memory intensive - but you'd be free to keep a session arround (as long as the database transaction is returned to the pool) for as long as you like and not worry about any old pojos that have gone out of scope.

Combine this with automatic versioning/refreshing - and it's a perfect solution!

I haven't implemented this myself yet as I will not be optimising until the end of the project. However, it would only take about half an hour to get working and I'd really rather not fork the hibernate code. Do you think this could be suggeted to the Hibernate team for the next release? Or, at the very least, a way to plugin your own implementation of PersistantContext... How do I go about making this suggestion?

In the mean time - the solution is posted here in principal, so it might proove useful to someone, or to me if I forget about it in three month's time!

Regards,

Ben.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.