-->
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.  [ 19 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: session-per-application in a rich client an antipattern?
PostPosted: Thu Sep 21, 2006 6:05 pm 
Newbie

Joined: Thu Sep 21, 2006 5:35 pm
Posts: 7
I've searched the boards for a while and seen a few posts alluding to the same issue but never a conclusive answer.

The application - swing rich client on a single user local db.

In this situation I think a session-per-application is desirable. If I load an entity, say the contact "Tom Hughes", I want only one object instance for that entity at any one time. Therefore if edit 'Tom Hughes" on my search screen, it is updated on my "Favourites Contacts" screen because it is the same object instance. Having a shared instance avoids me having stale data on my application's forms and avoids me having to listen to update events (via the interceptor or event mechanism or other means) and reload my forms as needed - this has a negative impact on performance, robustness and complexity.
I do realise the power of sessions and how they are used, please don't point me to here : http://hibernate.org/42.html#A11
I think though in my single useer db, I don't care about multiple sessions. They only serve to complicate.

Unfortunately I don't think I can implement a session-per-application because of the behaviour of the first level 'cache', ie. the session. That is, entities loaded into the session stay there until the session is closed.

I was thinking it may be possible to write a session that used weak references for all non-dirty entities. Entities could then be garbage collected when my app no longer needed them. I would be willing to contribute this work if feasible.

So the questions,
* I'm not a hibernate expert so are there any flaws in my reasoning?
* Is there an existing method to manage the first level cache?
* Is the suggestion of a weakly referenced session implementation feasible?

This would be super, super useful and from my research on the board, I'm not the only one having these problems.

thanks,
Tom Hughes


Top
 Profile  
 
 Post subject:
PostPosted: Sun Sep 24, 2006 8:21 pm 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
Quote:
I do realise the power of sessions and how they are used...

Unfortunately I don't think I can implement a session-per-application because of the behaviour of the first level 'cache', ie. the session. That is, entities loaded into the session stay there until the session is closed.


Wrong, evict() and clear() exist.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Sep 24, 2006 8:32 pm 
Newbie

Joined: Thu Sep 21, 2006 5:35 pm
Posts: 7
That doesn't seem enough though to manage a single session. For example :

Presumbly if I clear the session, all the entities become detached. Ths entities will be referenced by my ui components, which will mean lazy loading will now fail, and if I try and update a detached entity it will also fail without a tricky and bespoke reattachment of the object graph.

It's a problem!


Top
 Profile  
 
 Post subject:
PostPosted: Sun Sep 24, 2006 8:39 pm 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
No, it's not. You just have to learn how to use a persistence context and no magic weak references are going to help you do that.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Sep 24, 2006 8:45 pm 
Newbie

Joined: Thu Sep 21, 2006 5:35 pm
Posts: 7
Thanks for you time but I'm not following.

Say, I have a Person entity, 'Tom Hughes' and it is displayed in many different views. This instance can stay in these views for seconds, days, weeks or even months. I need that instance to stay in the session, so when I access lazily loaded attributes, they are loaded, and when I edit it, the updates work.
How can I know when I can evict that object from the session? ie. how do I know when I don't need it anymore? The only way to implement this is in Java, as far as I am aware is with a weak reference.

Tom.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Sep 24, 2006 8:55 pm 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
To me it seems like you once thought "Oh, I have to use one Session for this design" because you couldn't figure out how to work with several sessions. And now you are looking for a way to make this work. Have you considered that this wasn't the right decision?

I'm out from here on, as I did not use Hibernate ever with a single-threaded desktop application. For any multi-threaded application, there is basically no difference in the patterns that work, no matter if we talk about web, rich clients, or even multi-threaded desktop applications.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Sep 24, 2006 9:17 pm 
Newbie

Joined: Thu Sep 21, 2006 5:35 pm
Posts: 7
Quote:
To me it seems like you once thought "Oh, I have to use one Session for this design" because you couldn't figure out how to work with several sessions. And now you are looking for a way to make this work. Have you considered that this wasn't the right decision?


The history is that we wanted to use one session. Had many discussions and realised it wasn't possible for the reasons supplied (ie the session grows infinitely big). At the time, I trawled through this forum and the internet and found some similar questions but again, no good answers.

Utlimately we went for a multi session solution. Looking back now though it seems quite hacky and so I went thinking about an alternative solution. Had we missed something? The weak reference solution is what I came up with.

Quote:
For any multi-threaded application, there is basically no difference in the patterns that work, no matter if we talk about web, rich clients, or even multi-threaded desktop applications.


The important difference between rich client and web is that in a rich client I have many 'pages' or 'ui screens' open at once. When moving between those pages, the page is not reloaded. When I update something on one page, I expect it to be updated on the next.
With a web client I only really have one page open at once. I can have two open but I don't expect an update in one to be reflected in the other without a refresh.

T.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Sep 24, 2006 9:44 pm 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
Are we talking about a single-threaded desktop application (two tier), a multi-threaded desktop application (2 tier), or a rich client/multi-threaded server application (3 tier)?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 25, 2006 12:03 am 
Newbie

Joined: Thu Sep 21, 2006 5:35 pm
Posts: 7
a multi-threaded desktop application (2 tier). I'm not sure how the thread count makes any difference though(?)


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 25, 2006 1:08 am 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
So each thread uses its own Session and its own copy of database state. Use an event/listener system to refresh (and I don't mean refresh() on the session, but a new session) the state of each screen.

AFAIK Max Anderson built a pretty large three tier client/server application with this approach, and except for the non-existent network boundary between the presentation tier and the business tier, yours is the same. I'm sure that there are many other people who do the same.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 25, 2006 3:39 am 
Newbie

Joined: Thu Sep 21, 2006 5:35 pm
Posts: 7
Quote:
So each thread uses its own Session and its own copy of database state. Use an event/listener system to refresh (and I don't mean refresh() on the session, but a new session) the state of each screen.


So this is more or less how my application works. It does suck though having to use the event/listener system, it just makes things more complicated than they need to be. And more bug prone too. What does it buy me? Nothing.

How about this? I write an IdentityMap which sits on top of Hibernate and stores id -> entity using weak references. Every so often, I evict all the non dirty objects in the session that are not in the identity map. A bit (lot) of a hack and it means I'll have to synchronize access to my Session but it could work. Possible?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Sep 27, 2006 3:10 am 
Newbie

Joined: Thu Sep 21, 2006 5:35 pm
Posts: 7
Tom Hughes wrote:
How about this? I write an IdentityMap which sits on top of Hibernate and stores id -> entity using weak references. Every so often, I evict all the non dirty objects in the session that are not in the identity map. A bit (lot) of a hack and it means I'll have to synchronize access to my Session but it could work. Possible?


Ok this wont work as the session will still maintain strong references.

It seems that TopLink essentials (the reference implementation in GlassFish) does allow you to use weak references in sessions :
http://www.oracle.com/technology/products/ias/toplink/doc/1013/main/_html/cachun002.htm

In particular, this sounds like exactly what I need :
http://www.oracle.com/technology/products/ias/toplink/doc/1013/main/_html/cachun002.htm#CHEJDCBH

So is there definitely no chance this could make it into Hibernate? I would be willing to help with the work.

kind regards,
Tom Hughes


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 21, 2006 6:27 pm 
Newbie

Joined: Fri Sep 22, 2006 4:53 pm
Posts: 3
Hi Tom

(Hoping you are still watching this topic!)

We are in a similar position. Just about to start developing a rich client app with a local database. Currently single user but its possible in the future we may need to support a networked instance of the db and have the local clients access that instead.

I'd be interested in hearing whether you changed your plans and how things are working out using multiple sessions - or did you switch to Toplink?

My initial expectation after reading the various (admittedly sparse and limited) posts on this topic, is that we would go for a single session per interaction type approach. i.e. most user interactions would create a new session and would have to handle merging any detached objects back into that session as appropriate for update scenarios.

Then we would have to implement an event system to handle updates to other ui elements that might be displaying the same data. Presumably you would need some form of event mechanism anyway unless you had tied your persistent domain objects directly into your UI controls using some form of databinding approach? (Which is another area which I'd be interested in hearing how you tackled).

We are investigating using JPA rather than Hibernate/Toplink directly, and the jury is still out in terms of which implementation we will use. Hoping to delay that decision as long as possible and make it relatively easy to switch should either prove to be problematic.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 21, 2006 6:53 pm 
Newbie

Joined: Tue Feb 07, 2006 8:17 pm
Posts: 19
Hello,

The short answer is that I am still researching. However.

#1 I would recommend using a JPA approach, the annotations are much nicer than the XDoclet2 ones we were using and of course it theoretically allows you to switch JPA implementation with minimal changes.

#2 I think that an instance of a ui should only have one object instance per business entity. That means one session per application instance. If not you have to have a central event mechanism as you say. This can be done (in fact we've done it) but the problems are :
* bug prone. Two object instances representing the same entity can be inconsistent.
* has higher memory requirements.
* introduces more difficult session management. You have to be very careful where you put session management code :
* it can make reusing code more difficult.
* if you access a lazily loaded attribute of an object loaded in a closed session. BOOM -> Stack trace of doom.

If you have one open session, it's great, you can race around your object model, and your relationships get hydrated when needed. You don't have to worry about sessions. It just works.
You can't do this in hibernate because the session will constantly grow. In toplink essentials (aka glassfish) you can do this as it offers various weakly and softly references identity maps. When entities are not being used your application anymore, the garbage collector takes them away.

If anyone can explain if and why this is an antipattern then I'm listening.

Until then my recommendation is to use toplink essentials/glassfish-persistence (it's free!).

Tom


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 21, 2006 7:49 pm 
Newbie

Joined: Fri Sep 22, 2006 4:53 pm
Posts: 3
Quote:
#1 I would recommend using a JPA approach, the annotations are much nicer than the XDoclet2 ones we were using and of course it theoretically allows you to switch JPA implementation with minimal changes.


Providing you don't use any provider specific implementations that is... probably relying on TopLinks identity maps and a single application EntityManager would prevent you from switching to Hibernate JPA at a later time?

Quote:
* if you access a lazily loaded attribute of an object loaded in a closed session. BOOM -> Stack trace of doom.


This doesn't seem to be an issue with TopLink essentials. I noticed this didn't cause a problem but if I switched to Hibernate it did. I asked on the TopLink dev list and they say they explicitly designed to support lazy loading outside an open EntityManager session.

Quote:
You can't do this in hibernate because the session will constantly grow. In toplink essentials (aka glassfish) you can do this as it offers various weakly and softly references identity maps. When entities are not being used your application anymore, the garbage collector takes them away.


Yes, I read some of the docs that you linked to in your previous post. Still trying to digest them. So is that feature available through JPA/TopLink essentials as well or just the full blown TopLink implementation? I started searching looking for docs on TopLink essentials to see if they describe similar capabilities. It wasn't clear to me whether the cache they are talking about is equivalent to the JPA persistence context or something else. The cache overview describes TopLink as using two caches: a session cache and a unit of work cache. Do the identity map features you describe apply to both? Not sure. I guess I need to read more about the concept of sessions and caching in TopLink and then find out whether similar concepts apply to the JPA implementation.

Cheers
Martin


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 19 posts ]  Go to page 1, 2  Next

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.