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." <[EMAIL PROTECTED]> 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:[EMAIL PROTECTED]
> Sent: Wednesday, August 17, 2005 3:00 PM
> To: [email protected]
> 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/[email protected]/msg025
> 80.html
>
> http://www.mail-archive.com/[email protected]/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:[EMAIL PROTECTED]
> Sent: woensdag 17 augustus 2005 22:00
> To: '[email protected]'
> 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