-->
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.  [ 23 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Why Threadlocal pattern?
PostPosted: Thu Dec 11, 2003 1:16 pm 
Beginner
Beginner

Joined: Sun Sep 21, 2003 12:19 am
Posts: 40
I am starting to question about my Threadlocal design.

Here is the question. In terms of ThreadLocal pattern recommened on the website, it never clears to me when you should close the session. Most likely you are not? Since you don't know what that thread will do, right?

But all the reading telling me that I should 'close' the session ASAP (logic transaction done, which is a very fuzzy logic). If I close my session, then the threadlocal is no use to me since I have to rebuild the session next time the current thread try to access the session.

So I think the best approach is not using ThreadLocal and just open/close session on demand. But this will cause lazy load stuff complained closed session? I remeber I read somewhere I need some lock-mode setting, but could not find the reference anymore. Can anyone point me the resource?

Thanks.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Dec 11, 2003 1:27 pm 
Expert
Expert

Joined: Tue Sep 16, 2003 4:06 pm
Posts: 318
Location: St. Petersburg, Russia
Yes, you should close session when you do not need it anymore. Usually there are points when you need to open session and when you need to close it. Consider for example servlet filter - when it starts processing request, it opens session and puts it into ThreadLocal variable. Then the filter passes control to filter chain which means request eventually will arrive to servlet/JSP page and will be processed there. All the servet/JSP code use session obtained from ThreadLocal variable. When filter chain returns (normally or with exception), our filter closes session.

If you are ready to "open/close session on demand", that means you can put ThreadLocal's open/close in exactly the same places. ThreadLocal variable is nothing more than just a comfortable way to avoid passing session to all methods.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Dec 11, 2003 1:54 pm 
Beginner
Beginner

Joined: Sun Sep 21, 2003 12:19 am
Posts: 40
I understand what is the rational behind this pattern, just as you said--'avoid passing session' around. But what I am questioning is practicality.

An very simple example:
method1 inovke Threadlocal to get session, it triggers session creation.
method1 calls method2 which gain the existing session and function returns. Who close the session? well of course method1. but method2 can be invoked independly, so it has to close the session. So you will start seeing people inventing reference count into picture, that is exactly what Java tells us NOT to do. Why? Crash of one method could lead to reference count asymetric, and don't tell me put it into finally block, because that doesn't work nicely sometimes(such as you crashed before you getting the session) and defeats the purpose of simplicity of this pattern anyway.

Another follow up of the previous example is method1 doesn't call method2, rather method0 which has no knowledge of persistence calls method1 which needs to persist something and method0 then invokes call method2 which again need to persist something. When do you open and close the session using threadlocal?

To me the only valid way to use threadlocal is attach a timer-thread to time it out, we know how long the timer is just fell into fuzzy logic again.

Well then I think it is better to do it(timer) in Session code, what I mean is you can set a timeout when you create a session after inactivity for a while(QOS provided by buildsession call) the session close itself . Otherwise we have to do the way I said open/close at same spot. hmm.... starts to sound like C++ days.

No flame. Just want to know I do I reopen the session for those lazy loaders.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Dec 11, 2003 2:13 pm 
Expert
Expert

Joined: Tue Sep 16, 2003 4:06 pm
Posts: 318
Location: St. Petersburg, Russia
There are alot of discussion on this forum about this topic. http://forum.hibernate.org/viewtopic.ph ... emarcation for example. You may find more just bu typing "demarcation" or "transaction" in the search form.

To me it looks like none of your methodN should open/close session - this is a business for "outer" code.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Dec 11, 2003 2:28 pm 
CGLIB Developer
CGLIB Developer

Joined: Thu Aug 28, 2003 1:44 pm
Posts: 1217
Location: Vilnius, Lithuania
It must be safe to count references if you decrement counter in finally block, AOP must help to to it without any pain.

You can tell something like this for AOP framework:
"for all data access methods
before return:
if session is open then
decrement counter and
close session if counter == 0

before invoke:
if session is open then
increment counter "


Top
 Profile  
 
 Post subject:
PostPosted: Thu Dec 11, 2003 2:42 pm 
Beginner
Beginner

Joined: Sun Sep 21, 2003 12:19 am
Posts: 40
Not quite right. If you returns an iterator for lazy load, you don't want to decremented, if you do your session could be closed and the threadlocal is no good for you anyway. This is called reference count leaking.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Dec 11, 2003 2:48 pm 
Senior
Senior

Joined: Wed Aug 27, 2003 6:04 am
Posts: 161
Location: Linz, Austria
Check out the Spring Framework and its transaction management and Hibernate support: It provides clean solutions for this problem area, completely replacing custom ad-hoc solutions like ThreadLocal Sessions with associated Servlet Filters.

BTW, the upcoming release 1.0 M4 features a new OpenSessionInViewFilter/OpenSessionInViewInterceptor, still allowing for Spring's transaction management - for people that choose to accept the tradeoffs that the "Open Session in View" pattern involves.

Juergen
(Spring Framework developer)
http://www.hibernate.org/110.html


Top
 Profile  
 
 Post subject:
PostPosted: Thu Dec 11, 2003 2:49 pm 
CGLIB Developer
CGLIB Developer

Joined: Thu Aug 28, 2003 1:44 pm
Posts: 1217
Location: Vilnius, Lithuania
Yes, reference countin will not help if you need to return proxies, but it must be possible to find solution (Transaction callback, filter, command/action dispatcher)


Top
 Profile  
 
 Post subject:
PostPosted: Thu Dec 11, 2003 4:38 pm 
Beginner
Beginner

Joined: Sun Sep 21, 2003 12:19 am
Posts: 40
Thanks for the reply Juregen. I did looked at Spring before and I need some time to wrap around the idea.But that discussion could lead to a completely seperate thread which is no approperiate for this forum. Let's focus on Hibernate here.

Yeah, exactly as you said, ThreadLocal is just ad-hoc solution which is effective for avoid parameter passing but not safe.

And I think I found my answer of the question for session close/reattach:
Code:
if ( !Hibernate.isInitialized( foo.getBars()) )
    session.lock(foo, LockMode.NONE);


But this is way too intrusive for the user right? I really can not imagine I wrap such piece of code everywhere in my codebase. It more or less seems to be the proxy should do this for me. But how does Gavin know which Session to use if he wrap such call?

So he leaves us an interesting challenge to overcome with. No, I don't think Spring solves the problem since only bussiness method knows when to close the session. The bussiness method can be nested which leads to demacrate solution which is very similar to EJB's way of declaring a bean as tx required from external resouce, hmm....

Well, thanks for the attention. Let me think a little bit more on the design, and I will post my finding later.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Dec 11, 2003 4:47 pm 
Beginner
Beginner

Joined: Fri Oct 10, 2003 4:54 pm
Posts: 26
Location: Chicago, IL
no_ejb wrote:
An very simple example:
method1 inovke Threadlocal to get session, it triggers session creation.
method1 calls method2 which gain the existing session and function returns. Who close the session? well of course method1. but method2 can be invoked independly, so it has to close the session. So you will start seeing people inventing reference count into picture, that is exactly what Java tells us NOT to do. Why? Crash of one method could lead to reference count asymetric, and don't tell me put it into finally block, because that doesn't work nicely sometimes(such as you crashed before you getting the session) and defeats the purpose of simplicity of this pattern anyway.


If you are willing to follow the IoC pattern similar to Spring, you could do the following (note this is a simple example, you could easily start adding interfaces, etc, but then you should really consider Spring since it already does this)

Code:

public abstract class HibernateBlock {
    public abstract Object runInHibernate(Session session) throws HibernateException;

    public void execute() throws HibernateException {
        boolean wasSessionCreated = false;
        Session session = (Session)someThreadLocal.get();
        if (session == null) {
            session = someHibernateSessionFactory.createSession();
            wasSessionCreated = true;
        }
        try {
            runInHibernate(session);
        } finally {
            if (wasSessionCreated) {
                session.close();
        }
    }
}



And then to use this block:

Code:

    public Object someMethod(final Object param1) {
        Object result = new HibernateBlock() {
            public Object runInHibernate(Session session) {
                 // do stuff with the hibernate session
            }
        }
        return result;
    }



There are some things that will be awkward with this approach such as the syntax of the anonymous inner class, needing to declare method parameters final, having to cast the result object from the block, and somewhat quirky dealing with typed exceptions, but it solves exactly the problem you presented.

Some of the awkwardness can be resolved if you turn to AOP (which is one technique that Spring offers, but doesn't require).

At any rate, there are options out there that aren't that difficult.
[/code]


Top
 Profile  
 
 Post subject:
PostPosted: Thu Dec 11, 2003 5:10 pm 
Beginner
Beginner

Joined: Sun Sep 21, 2003 12:19 am
Posts: 40
loverde,
re-read my example of iterator. You are missing the point of leaking reference, either int or boolean, they are the same to me. Spring is no help here.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Dec 11, 2003 7:24 pm 
Beginner
Beginner

Joined: Sun Sep 21, 2003 12:19 am
Posts: 40
As discussed I updated wiki Thread Local Session for a auto-timeout session implementation.

I am continuing thinking for a better solution.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Dec 11, 2003 7:26 pm 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
I don't see the problem. You know when the execution of your thread starts, in almost all situations: HTTP request coming in, SOAP request, whatever. You also know in most situation when your thread is finished: A view is completely rendered, a response is send, whatever. The only thing you have to do is: Attach an Observer/Observable (or a ServletFilter!) to your ThreadLocal management.

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


Top
 Profile  
 
 Post subject:
PostPosted: Thu Dec 11, 2003 8:42 pm 
Beginner
Beginner

Joined: Fri Oct 10, 2003 4:54 pm
Posts: 26
Location: Chicago, IL
no_ejb wrote:
loverde,
re-read my example of iterator. You are missing the point of leaking reference, either int or boolean, they are the same to me. Spring is no help here.


No, look at my example code. It will be impossible for code using Hibernate not to correctly close the session. That is the point of the inversion of control pattern. To further expand the example:


Code:

    public Object someMethod(final Object param1) {
        Object result = new HibernateBlock() {
            public Object runInHibernate(Session session) {
                 // do stuff with the hibernate session

                 someOtherMethod();

                 // ...
            }
        }
        return result;
    }

    public Object someOtherMethod() {
        Object result = new HibernateBlock() {
            public Object runInHibernate(Session session) {
                 // do stuff with the hibernate session
            }
        }
        return result;
    }



Notice how if a caller were to call "someMethod" first, it's HibernateBlock instance would create the session and associate it with the thread local (missing from my original HibernateBlock code, but the intent was to give the general idea). Internally when "someMethod" calls "someOtherMethod" the HibernateBlock inside of that method will reuse the ThreadLocal.

If instead, a caller invokes "someOtherMethod" first, it's HibernateBlock instance will create the session and associate it with the thread local.

Using this approach eliminates the need for your application code to use an error prone "finally" block. Basically, this approach is the Java idiom that mimics the old C++ idiom of using an object defined on the stack to guarantee that resources would be freed when a method completes. No reference counting is required in any way.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Dec 11, 2003 8:47 pm 
Beginner
Beginner

Joined: Fri Oct 10, 2003 4:54 pm
Posts: 26
Location: Chicago, IL
Also, yet another approach would be to use CGLIB to enhance your business services with the same type of logic that was in the HibernateBlock.

Of course, such an enhancement starts to enter into the realm of exactly what SLSBs provide...


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 23 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.