-->
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.  [ 12 posts ] 
Author Message
 Post subject: Session-per-transaction or ThreadLocalSession?
PostPosted: Thu Apr 01, 2004 1:26 pm 
Beginner
Beginner

Joined: Wed Feb 25, 2004 6:23 pm
Posts: 39
I'm revisiting this topic because I'm implementing my business logic behind stateless session beans. I could be wrong, but I don't think http://hibernate.org/42.html (ThreadLocalSession) applies to this situation. What I really want is a session-per-transaction here, but after thinking it through, I realize this could be tricky. First, an SLSB instance, while living in a single thread, can be invoked by multiple clients. This means that if I associate a Session with the thread, then I could face this:

1. Client A starts transaction, calls business method on SLSB.
2. SLSB creates a new Session and associates it with thread.
3. Client B starts transaction, calls business method on SLSB.
4. SLSB reuses the Session created for Client A and Client A's transaction.

This could be big trouble, no? It seems in an SLSB what I really want is to associate the Session with the current transaction, not with the current thread. So, the next question is, how do I reliably associate a Session with a transaction? After poking around the TransactionManager API, I see that it has a "getTransaction()" method that gets "the transaction object that represents the transaction context of the calling thread". Is it safe to assume that getTransaction() will always return the same instance of the Transaction object for the same transaction, even across multiple SLSB calls, and that it will not reuse instances for different transactions? In other words, could I key my Session off of the Transaction instance? Example:
Code:
public Session getSession()
{
  TransactionManager tm = [get current TransactionManager];
  Transaction currentTransaction = tm.getTransaction();
  Session session = (Session)sessionMap.get(currentTransaction);
  if(session == null)
  {
    session = [get new session from SessionFactory];
    sessionMap.put(currentTransaction, session);
    [register with Transaction so that we remove session from map when transaction is finished]
  }
  return session;
}


Thoughts?


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 01, 2004 4:29 pm 
CGLIB Developer
CGLIB Developer

Joined: Thu Aug 28, 2003 1:44 pm
Posts: 1217
Location: Vilnius, Lithuania
As I understand EJB and JTA it must be better to use statefull beans for transaction propagation, stateles bean executes transaction per method and the same method can not run in multiple thread, so your problem doe's not exits too. For statefull beans you need ThreadLocal on client (bean per client thread/transaction) and Synchronization callback on server, for stateles bean you need threadloacal and reference counting on server.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 01, 2004 5:52 pm 
Beginner
Beginner

Joined: Wed Feb 25, 2004 6:23 pm
Posts: 39
Maybe I'm misunderstanding stateless session beans then. I was under the impression that a SLSB had these properties:
1. All calls are serialized to the SLSB by the container (thread safety).
2. All method invocations on the SLSB happen in the same thread.
3. If a transaction is present when a client invokes a method on a SLSB, and the method is properly marked, then the method invocation will participate in the client's transaction.
With these three things in mind, doesn't it make sense that method calls to a SLSB, while all occurring in the same thread, could be interleaved between multiple clients and transactions? For example, take this pseudo-code running on the client side:
Code:
UserTransaction tx = [get UserTransaction];
tx.begin();
MySLSB slsb = [get SLSB];
slsb.method1();
slsb.method2();
tx.commit();

Imagine two clients executing this at the exact same time. The first client is "Client A", and Client A's transaction we'll call "Transaction A"... likewise for "Client B". The server may choose to serialize calls to a single instance of the stateless session bean, and it may do it in this order:
1. Client A calls method1() which participates in Transaction A
2. Client B calls method1() participating in Transaction B
3. Client A calls method2() participating in Transaction A
4. Client B calls method2() participating in Transaction B
Here we have four method invocations from two clients in two separate transactions being serialized to the same instance on the same thread. If we want to keep a Session for the duration of a transaction (on the server side), and if I understand all this correctly, then ThreadLocal alone won't work.. we'll need a way to associate a Session with a transaction. When a method is called, on the server side, we pull the Session for the current transaction.
Does this make sense, or am I mistaken?
Thanks,
Anodos


Top
 Profile  
 
 Post subject: Re: Session-per-transaction or ThreadLocalSession?
PostPosted: Thu Apr 01, 2004 6:14 pm 
Newbie

Joined: Sat Sep 13, 2003 12:45 am
Posts: 12
Location: Rochester, NY
Are you saying that you want multiple remote invocations of methods in a set of SLSBs to participate in a single transaction? If so, it would seem to me that you are trying to give state to a stateless protocol, which would explan why things aren't hanging together. The way I understand it each method of a SLSB that you call remotely is a unit of work and should be committed or rolled back when the method is done. If not how would the server know what to do with a pending transaction if the client goes away for some reason between remote method calls?

_________________
Jim


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 02, 2004 1:10 am 
CGLIB Developer
CGLIB Developer

Joined: Thu Aug 28, 2003 1:44 pm
Posts: 1217
Location: Vilnius, Lithuania
Yes, "Stateless" means no client state and no transaction propagation(transaction per remote method, but all local methods called by remote method will be in the same transaction/thread if method "supports" it). Probably you want statefull beans, there is no problems to store bean reference in threadlocal on client and you do not need threadlocal on server (use TransactionSynchronization interface)


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 02, 2004 11:20 am 
Beginner
Beginner

Joined: Tue Mar 02, 2004 6:17 pm
Posts: 20
This has been a bit confusing for me for quite a while too.

Let's say we have the following three SLSBs that form a hierarchy of business facade and all uses Hibernate based DAOs (it may not look like an example with good logic, but just gives an idea):

Code:
SLSB1{
  private Configuration DAO configDAO;
  private ServiceInterface1Home sLSBHome1;
  private ServiceInterface2Home sLSBHome2;

  public void transactionGlobal(){
     getService1().subTransaction1();
     getService2().subTransaction2();
  }
}

SLSB2 {
  private BookDAO bookDao;
  private StoreDAO storeDao;
 
  public void subTransaction1(){
     ...
  }
}

SLSB3 {
  private BuyerDAO buyerDao;
  private SellerDAO sellerDao;

  public void subTransaction2(){
     ...
  }
}

(Transaction attribute of all SLSB methods are "required")


In this case, it seems reasonable for me to expect that SLSB1 controls the creation and closure of the Hibernate session since it is always the demarcation point of global transactions.

Now question #1: in a single "global" transaction, will SLSB1, 2, 3 and all their DAOs access the same "ThreadLocal" hibernate session?

In another scenario, say, "subTransactionX" methods of SLSB2 and 3 can also be an independant transaction, in addition to being used by SLSB1 as sub-transactions.

question #2: is it a viable practice to still use "ThreadLocal" sessions and just open a new session when get() returns null?

thanks,
Dan


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 02, 2004 11:25 am 
Beginner
Beginner

Joined: Tue Mar 02, 2004 6:17 pm
Posts: 20
Anodos wrote:
Code:
UserTransaction tx = [get UserTransaction];
tx.begin();
MySLSB slsb = [get SLSB];
slsb.method1();
slsb.method2();
tx.commit();



I think the only significant benefit of using SLSBs with Hibernate is the container managed transaction. In above quoted code, you are tring to use SLSB as merely a thread-safe object that holds some business logic.

Am I misunderstanding your point?

Dan


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 02, 2004 11:39 am 
Newbie

Joined: Thu Apr 01, 2004 3:36 pm
Posts: 13
Location: New York
Anodos,

The natural way to handle a client transactions spanning multiple SLSB invocations is to declare the SLSB method with transaction=Required and get a new Session in each method invocation. Before returning, you flush and close the session. The appserver takes care of commiting the transaction when appropiate.

Each time the session get a connection from the datasource, the appserver will associate it with the current transaction context. Thus there is no problem if the client calls are inteleaved.

Rememeber that the session is a lightweight object and you don't get any performance boost by caching it.

Does this answer your question?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 02, 2004 11:48 am 
Newbie

Joined: Thu Apr 01, 2004 3:36 pm
Posts: 13
Location: New York
Dan,

I see you guys are all taking the ThreadLocal pattern as given and try to work around it. What is wrong with obtaining and closing the session in each SLSB method?

This way the methods are decoupled and can be called by the client any way it wants. Moreover, there is no housekeeping of the thread local storage.

Cheers,

Bogdan.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 02, 2004 12:51 pm 
CGLIB Developer
CGLIB Developer

Joined: Thu Aug 28, 2003 1:44 pm
Posts: 1217
Location: Vilnius, Lithuania
bcalmac wrote:
Dan,
I see you guys are all taking the ThreadLocal pattern as given and try to work around it. What is wrong with obtaining and closing the session in each SLSB method?
Bogdan.

There is nothing wrong for remote SLSB method to close/open session per remote method and you must to do it.
if you delegate for plain services or private implementation methods and need to call data access methods in the same transaction (transaction on server per single remote method , but multiple data access methods per remote method) then ThreadLocal session is usefull.
You can use session as parameter in implementation methods, it is the same, but ThreadLocal is a workaround for service abstraction and it "hides" this parameter as implementation details.
If your data access code is in remote method implementation then you do not need any threalocals, but this kind of code is hard to test.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 02, 2004 1:04 pm 
Beginner
Beginner

Joined: Tue Mar 02, 2004 6:17 pm
Posts: 20
Exactly!

I'm having many data accessing methods with signature like
Code:
xxx(Session s, DTO dto, .....)


It works find but is annoying. Besides, it forces my design to be tied with Hibernate, which I would like to avoid.

All I'm still hesitating about this ThreadLocal thing is because I'm not quite sure whether it really works reliably in SLSB + DAO pattern (not quite familiar with ThreadLocal yet). Like described in the post above.

Dan


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 02, 2004 2:07 pm 
CGLIB Developer
CGLIB Developer

Joined: Thu Aug 28, 2003 1:44 pm
Posts: 1217
Location: Vilnius, Lithuania
Yes, it is annoying. Probably you need more this kind of parameters like
"currentUser", but data access object instance per remote method and "currentSession","currentUser" as constructor or factory method parameters is not a bad way too. I prefer ThreadLocal, it is a very trivial thing, it looks like as map with current thread as key.

Code:
Object get(){
return map.get(Thread.currentThread());
}

void set(Object value){
   map.put(Thread.currentThread(),value);
}


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