Exceptional Transactions and Bad AOP Idioms
I needed yet-another-cmt-in-j2se so went about it the "right way" -- using aspects. It drilled into me a serious trap I have fallen into -- using globals (static singletons) for communication with aspects =/ Lets look at what I am doing:
This is a simple implementation of container manager transactions in AspectJ =) It doesn't support all six declarations, but only the four that I actually use (requires, supports, never, mandatory). Supports is the default.
package org.skife.transition;
public abstract aspect Transition
{
abstract pointcut require();
abstract pointcut mandatory();
abstract pointcut never();
pointcut transacted() : require() && !cflowbelow(require());
before() : never() {
Transaction tx = TxProxy.instance().currentTransaction();
if (tx != null && tx.isInProgress()) {
throw new IllegalStateException("'NEVER' tx method invoked inside tx");
}
}
before() : mandatory() {
Transaction tx = TxProxy.instance().currentTransaction();
if (tx == null || !tx.isInProgress()) {
throw new IllegalStateException("'MANDATORY' tx method invoked outside tx");
}
}
/**
* Begin a transaction if one is not in progress
*/
before() : transacted() {
Transaction tx = TxProxy.instance().currentTransaction();
if (tx == null) {
tx = TxProxy.instance().newTransaction();
}
if (!tx.isInProgress()) {
tx.begin();
}
}
/**
* Commit Transaction
*/
after() returning : transacted() {
Transaction tx = TxProxy.instance().currentTransaction();
if (tx != null && tx.isInProgress()) {
tx.commit();
}
}
/**
* Rollback on exception
*/
after() throwing : transacted() {
Transaction tx = TxProxy.instance().currentTransaction();
if (tx != null && tx.isInProgress()) {
tx.rollback();
}
}
}
Once again it uses a singleton helper class to handle interactions with the external system (whatever provides the transaction service -- JDBC, OJB, JTA, Hibernate, Spring, etc). This type of singleton bridge seems to be coming up a lot in my aspects, unfortunately. I think it points out a serious weakness in my knowledge of how to use the tool.
Adrian Colyer has done some work with letting Spring configure aspects in AspectJ, and I need to play with this some more. That may be an answer. He seems to use rather intimate knowledge of how AspectJ compiles aspects in though, which I am not sure I am comfortable depending on if it isn't part of the spec =/
The problem I run into is when I need to have the same aspects talking to different component implementations in the same VM. BANG. It is the wonderful service-lookup issue all over again.