and i'll just chip in.  I do think AspectJ can help with your logic - but
Spring may be a good answer too.

> 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.

something like that is simply:

before(): handler(C_DoesNotExist) {...}

to choose a particular catch block you also throw in a cflow(...) or a
withincode(...)

but just exploring some options, here are some possibilities:

// remove all the 'stuff' from doOperationX
around(): execution(@Transactional * *(..)) {

    connection = get_connection()
    connection.start_transaction()
    try {
      proceed();

      connection.commit();
    } finally {
        connection.end_transaction()  //rolls back uncommitted
        connection.close()
    }
}

// if calling updateC from updateB and it fails, just ignore it
around(): call(* updateC(..)) && withincode(* updateB(..)) {
  try {
    proceed();
  } catch (C_DoesNotExist) {
    // ignore
  }
}

@Transactional function doOperationX()
{
        updateA(connection)
        updateB(connection)
}

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()
}


Andy


2009/8/11 Adam Bennett <[email protected]>

>  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
>
>
_______________________________________________
aspectj-users mailing list
[email protected]
https://dev.eclipse.org/mailman/listinfo/aspectj-users

Reply via email to