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