ibatis-user-java mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Barnett, Brian W." <brian.barn...@pearson.com>
Subject RE: Transaction question
Date Thu, 18 Aug 2005 16:25:07 GMT
Prashanth,
Your suggestion is precisely what I did on a previous project. (The "service
delegate" mentioned below.) I had a whole slug of methods whose sole
responsibility was to start and end transactions, and it got cumbersome. For
example, I might have an updateWidget() method in a service layer class. I
then would also have an updateWidget() in the "service delegate" to provide
the transaction handling which turns around and calls updateWidget() in the
service layer... a proliferation of methods.

It is this proliferation of methods that I want to get away from.

-----Original Message-----
From: Prashanth Sukumaran [mailto:prashanthsukumaran@yahoo.com] 
Sent: Thursday, August 18, 2005 10:15 AM
To: user-java@ibatis.apache.org
Subject: RE: Transaction question


Hi,

Do we really have to do all this in the name of reusability.  Can't you
change the way you code? 
Can't you overload/refactor a method and have the transaction externalized.

Assume you have 

methodA
startTransaction();
     // do some business logic.
     callDAO.doSomething();
endTransaction();

Instead change it to

methodA [    // All that methodA is used is for now Transaction
Encapsulation and not anything
else.
    startTransaction()
    methodB
    endTransaction()
]

methodB [
    // do some business logic.
    callDAO.doSomething();
]

In a different service manager instead of calling the methodA and hence
having nested transactions, can't you call methodB instead.

Rgds

Prashanth Sukumaran.

 

--- "Barnett, Brian W." <brian.barnett@pearson.com> wrote:

> Niels,
> Thanks for the info. Maybe I am not totally understanding how your 
> modified code works, but is it meant to handle nested transactions?
> 
> If a transaction has already been started, then your modified code 
> will simply call invoke. I understand that. What happens when a nested 
> transaction calls commitTransaction()? (Like doSomethingElse() calling
> doSomething() in the sample code below.) commitTransaction() gets 
> called twice in this example. I believe it will throw an exception.
> 
> What I was considering was to add a ThreadLocal transactionCounter 
> variable to DaoContext. start, commit and end transaction methods 
> might look something like this:
> 
>   public void startTransaction() {
>     transactionCounter++;          // <-- NEW LINE OF CODE
>     if (transactionCounter == 1) { // <-- NEW LINE OF CODE
>       if (state.get() != DaoTransactionState.ACTIVE) {
>         DaoTransaction trans = transactionManager.startTransaction();
>         transaction.set(trans);
>         state.set(DaoTransactionState.ACTIVE);
>         daoManager.addContextInTransaction(this);
>       }
>     }                              // <-- NEW LINE OF CODE
>   }
> 
>   public void commitTransaction() {
>     if (transactionCounter == 1) { // <-- NEW LINE OF CODE
>       DaoTransaction trans = (DaoTransaction) transaction.get();
>       if (state.get() == DaoTransactionState.ACTIVE) {
>         transactionManager.commitTransaction(trans);
>         state.set(DaoTransactionState.COMMITTED);
>       } else {
>         state.set(DaoTransactionState.INACTIVE);
>       }
>     }                              // <-- NEW LINE OF CODE
>   }
> 
>   public void endTransaction() {
>     try {                            // <-- NEW LINE OF CODE
>       if (transactionCounter == 1) { // <-- NEW LINE OF CODE
>         DaoTransaction trans = (DaoTransaction) transaction.get();
>         if (state.get() == DaoTransactionState.ACTIVE) {
>           try {
>             transactionManager.rollbackTransaction(trans);
>           } finally {
>             state.set(DaoTransactionState.ROLLEDBACK);
>             transaction.set(null);
>           }
>         } else if (transactionCounter == 1) {
>           state.set(DaoTransactionState.INACTIVE);
>           transaction.set(null);
>         }
>       }                     // <-- NEW LINE OF CODE
>     } finally {             // <-- NEW LINE OF CODE
>       transactionCounter--; // <-- NEW LINE OF CODE
>     }                       // <-- NEW LINE OF CODE
>   }
> 
> The idea being that the transaction related logic only executes when 
> we are dealing with the first transaction bracket that was opened. I 
> haven't actually tried this out, but I think I will. Let me know if 
> you, or anyone else, sees any problems with this approach.
> 
> Thanks,
> Brian Barnett
> 
> -----Original Message-----
> From: Niels Beekman [mailto:n.beekman@wis.nl]
> Sent: Wednesday, August 17, 2005 3:00 PM
> To: user-java@ibatis.apache.org
> Subject: RE: Transaction question
> 
> 
> Hi,
> 
> I'm facing this exact same problem however in a somewhat different 
> context, see the following archived thread:
> 
> http://www.mail-archive.com/ibatis-user-java@incubator.apache.org/msg0
> 25
> 80.html
> 
> http://www.mail-archive.com/user-java@ibatis.apache.org/msg00036.html
> 
> I recently restarted my investigation into this problem and have tried 
> some hacks in the iBATIS code, the changes were made in DaoProxy.java 
> (which proxies DAO-interfaces to provide transaction-semantics) and 
> DaoContext.java (which handles the transactions itself). Of course 
> this is rather messy, but I really do not like the SavePoint-support 
> mentioned in the thread above, I think it is rather a workaround than 
> a solution.
> 
> Anyway, my changes (totally unverified, without any guarantees) in 
> package
> com.ibatis.dao.engine.impl:
> 
> DaoContext.java, added isTransactionRunning():
> 
> public boolean isTransactionRunning() {
>   return transaction.get() != null;
> }
> 
> DaoProxy.java, modified invoke(): see attached file.
> 
> This seems to work pretty good in my case, however further 
> investigation is required.
> 
> I hope the iBATIS devteam can comment on my solution, whether you 
> think it will work, or when you believe it really sucks :)
> 
> Greetings,
> 
> Niels
> 
> -----Original Message-----
> From: Barnett, Brian W. [mailto:brian.barnett@pearson.com]
> Sent: woensdag 17 augustus 2005 22:00
> To: 'user-java@ibatis.apache.org'
> Subject: Transaction question
> 
> What are some good options to deal with the following:
> 
> ServiceClass1
> public void doSomething() {
> 	try {
> 		daoManager.startTransaction();
> 		// Write some stuff to a database
> 		daoManager.commitTransaction();
> 	} catch (Exception e) {
> 		throw e;
> 	} finally {
> 		daoManager.endTransaction();
> 	}
> }
> 
> ServiceClass2
> public void doSomethingElse() {
> 	try {
> 		daoManager.startTransaction();
> 		ServiceClass1 sc1 = new ServiceClass1();
> 		sc1.doSomething();
> 		// Write some stuff to a database
> 		daoManager.commitTransaction();
> 	} catch (Exception e) {
> 		throw e;
> 	} finally {
> 		daoManager.endTransaction();
> 	}
> }
> 
> The doSomethingElse() method will fail because startTransaction() gets 
> called twice. I need a good way to be able to re-use business logic 
> methods in different, or the same, service layer classes.
> 
> One thing I have done in the past is create a whole new layer, 
> essentially a service delegate, where I have moved all the transaction 
> logic to. I didn't like that too much because it was just a huge 
> proliferation of methods just to solve the "no nested transaction" 
> problem.
> 
> I have also passed flags into methods to indicate if a transaction has 
> already been started, but passing flags is messy to say the least.
> 
> Any great ideas out there?
> 
> TIA,
> Brian Barnett
> 
> **********************************************************************
> **
> **** 
> This email may contain confidential material. 
> If you were not an intended recipient, 
> Please notify the sender and delete all copies. 
> We may monitor email to and from our network. 
> ************************************************************************
> ****
> 
> **********************************************************************
> ******
> This email may contain confidential material. 
> If you were not an intended recipient, 
> Please notify the sender and delete all copies. 
> We may monitor email to and from our network. 
>
****************************************************************************
> 



		
____________________________________________________
Start your day with Yahoo! - make it your home page 
http://www.yahoo.com/r/hs 
 

**************************************************************************** 
This email may contain confidential material. 
If you were not an intended recipient, 
Please notify the sender and delete all copies. 
We may monitor email to and from our network. 
****************************************************************************

Mime
View raw message