ORM would probably be too much change at once - much of our code base is very 
procedural.  We might consider Spring because it sounds like it could be 
refactored in incrementally.  Yet I fear that even with Spring it is still the 
programmers responsibility write explicit rollback logic when catching 
exceptions (I need to read up on Spring though).  

Can AspectJ be used somehow to automatically install a hook inside the 
catch(C_DoesNotExist)  block?  If so that would let me make the rollback 
implicit.


  _____  

From: Ron Difrango [mailto:[email protected]]
To: [email protected]
Sent: Tue, 11 Aug 2009 07:01:08 -0700
Subject: Re: [aspectj-users] Database transactions and exceptions don t mix! 
(can AspectJ help?)

          My initial reaction to this, is why don’t you use either an ORM 
framework or Spring to help you manage the transactions?
  
  
  On 8/10/09 11:39 PM, "Tahir Akhtar" <[email protected]> wrote:
  
  You might want to read : InfoQ: Java Transaction Design Strategies 
<http://www.infoq.com/minibooks/JTDS> 
  http://www.infoq.com/minibooks/JTDS
  
  Adam Bennett wrote: 
   
  Lately I've been trying to improve how our web application employs 
transactions (we don't use them enough). While doing this I became aware of 
this rather general problem. It seems as though database transactions cannot be 
mixed with exceptions unless great vigilance is practiced.  I'm wondering if 
AspectJ can help me in some way.
  
  Consider this pseudo code:
  
  
  function doOperationX()
  {
      connection = get_connection()
      connection.start_transaction()
      try
      {
          updateA(connection)
  
          try
          {
              updateB(connection)
          }
          catch (C_DoesNotExist)
          {
              //ignore (non fatal)
          }
  
          connection.commit()
      }
      finally
      {
          connection.end_transaction()  //rolls back uncommitted
          connection.close()
      }
  }
  
  function updateA(connection)
  {
      connection.execute("UPDATE a SET ...")
  }
  
  function updateB(connection)
  {
      connection.execute("UPDATE b SET ...")
      updateC(connection)
  }
  
  function updateC(connection)
  {
      result = connection.execute("SELECT c.id FROM c INNER JOIN b ON ...")
      if (result.next())
          connection.execute("UPDATE c SET ...")
      else
          throw C_DoesNotExist()
  }
  
  
  
  Don't study the pseudo SQL too closely, the problem isn't there. Read the 
code like this:
  
  1) operationX requires updating of A and, optionally, B.
  2) Internally, updating B always requires that C also be updated. All or 
nothing.
  3) Sometimes, C cannot be updated because the database is not in the proper 
state at this time. (Not an invalid state, mind you)
  4) operationX knows that C might not be updatable, so it catches the 
exception and ignores it.
  
  The problem is:
  
     updateB() leaves the database in an inconsistent state if an exception is 
thrown
     out of updateC().  The inconsistency is that table B has been updated but 
D has
     not been updated accordingly.
  
  Yet, it's only a problem because operationX caught the exception. Had it let 
the exception continue up, the finally block would have rolled back the entire 
transaction quite nicely.
  
  How can I avoid this problem? The only proper solution that I can see is a 
prolific use of transaction checkpoints (aka savepoints) so that a partial 
rollback can occur if needed:
  
  
  function updateB(connection)
  {
      success = false
      savepoint = connection.setSavepoint()
      try
      {
          connection.execute("UPDATE b SET ...")
          updateD(connection)
          success = true
      }
      finally
      {
          if (not success)
              connection.rollback(savepoint)
      }
  }
  
  
  
  But this hurts performance considerably and requires programmer vigilance and 
lots of extra code! The programmer must remember that:
  
    **If your function does more than one update it MUST use a savepoint!**
  
  That's tough pill to swallow (for me). I try to avoid programming models that 
require programmer vigilance. All it takes is one groggy Monday...
  
  What do you think? Am I missing a better solution?  Can AspectJ help?
  
  Videx Inc. 1105 N. E. Circle Blvd. Corvallis OR 97330 (541) 758-0521
  CONFIDENTIAL COMMUNICATION: The email message and any attachments are 
intended only for the addressee.  They may be privileged, confidential, and 
protected from disclosure. If you are not the intended recipient, any 
dissemination, distribution, or copying is expressly prohibited.  If you 
received this email message in error, please notify the sender immediately by 
replying to this e-mail message or by telephone
  
  _______________________________________________
  aspectj-users mailing list
  [email protected]
  https://dev.eclipse.org/mailman/listinfo/aspectj-users
  
  
    
  
  
    _____  

_______________________________________________
  aspectj-users mailing list
  [email protected]
  https://dev.eclipse.org/mailman/listinfo/aspectj-users
  
  Ron DiFrango            
  Manager and Architect  |  CapTech Ventures
  (804) 855-9196-6308  |  [email protected]
            


Videx Inc. 1105 N. E. Circle Blvd. Corvallis OR 97330 (541) 758-0521
CONFIDENTIAL COMMUNICATION: The email message and any attachments are intended 
only for the addressee.  They may be privileged, confidential, and protected 
from disclosure. If you are not the intended recipient, any dissemination, 
distribution, or copying is expressly prohibited.  If you received this email 
message in error, please notify the sender immediately by replying to this 
e-mail message or by telephone
_______________________________________________
aspectj-users mailing list
[email protected]
https://dev.eclipse.org/mailman/listinfo/aspectj-users

Reply via email to