Another dream with transactions and AOP today. And boy, this one was
gooooood. I wrote about it, but Roller ate my post. Well, shit happens.
Here's what I could recover from it.
What we have today to make this possible:
Most RDBMSs today support nested transactions
AspectWerkz supports transparent persistence for objects, advices and introductions using Prevayler and JISP
Hibernate handles almost-transparent persistence for objects on RDBMSs
AspectWerkz supports definition of aspects and introductions using meta-data attributes (xdoclet-like tags)
There are lots of other cool features on AspectWerkz I haven't been able to play with in this area (PersistenceManagers, etc)
Lots of people interested in AOP willing to get their hands dirty on some hardcore AOP aspects
Ok. Throw it all on a blender. Here's what you have:
/** * @persistent */ public class Customer { private String name; private String id; private Address address;
/** * @persistent */ public class CustomerManager { private List customers = new ArrayList();
/** * @transaction createNew rollbackOnException */ public Customer addCustomer(String name, String id, Address address) { Customer c = new Customer(); c.setName(name); c.setId(id); c.setAddress(address); customers.add(c); return c; } }
Then, this is what should happen at startup:
The PersistenceManager connects to the database and checks for the
existence of the tables Customer, Address and CustomerManager. As they
don't exist yet, it creates them:
CREATE TABLE "CustomerManager" ( "uuid" VARCHAR(32) NOT NULL PRIMARY KEY, "customers_uuid" VARCHAR(32) NOT NULL );
The application starts up normally. Then, somewhere, somehow,
CustomerManager is instantiated. The AOP framework know about it, and
has an advice to help filling that customers ArrayList with data from
the database. As there's no data in there yet, execution proceeds. The
addCustomer method is called. The AOP framework knows about it too, and
it sees the @transaction tag, and starts doing its job. It asks the
persistence manager to create a new transaction, and execution starts.
Suddenly, hey! We're creating a new instance of a customer! The
persistence manager creates a new nested transaction, and INSERTs it,
with a newly created UUID, into the Customer table. Everything goes
well, so it commits the nested transaction, and execution proceeds.
Ah, now we're setting some properties. Cool. The setName, setId and
setAddress methods are marked with @transaction useExistent, so no new
transactions are created. Fields name, id and address are set, and the
persistence manager UPDATEs the table accordingly.
Then, the new, fresh, beautiful Customer object is being added to a
List. The AOP framework sees that, too, and asks the persistence
manager to do something about it. "Piece of cake!", the persistence
manager says, and INSERTs a new row into the CustomerManager table.
Oh, the method is returning. So soon, already? "Ok", says the persistence manager, "let's commit this transaction."
Want to re-read the same story using another syntax? Okay, here you go:
SELECT COUNT(*) FROM "CustomerManager";
BEGIN CustomerManager_addCustomer
BEGIN Customer_ctor INSERT INTO "Customer" VALUES ('168c129ac3be239d91a0a834432c27a9',NULL,NULL,NULL); COMMIT Customer_ctor
UPDATE "Customer" SET "name"='Carlos Villela' WHERE "uuid"='168c129ac3be239d91a0a834432c27a9';
UPDATE "Customer" SET "id"='cv' WHERE "uuid"='168c129ac3be239d91a0a834432c27a9';
UPDATE "Customer" SET "address"='9572c81ec1b149121926bacd39678ffe' WHERE "uuid"='168c129ac3be239d91a0a834432c27a9';
BEGIN CustomerManager_customers_add INSERT INTO "CustomerManager" VALUES ('f39cab12831bc1d39f33012dee19237a','168c129ac3be239d91a0a834432c27a9'); COMMIT CustomerManager_customers_add
COMMIT CustomerManager_addCustomer
Is this already possible, is it already viable, is it something we can
build today, or is there a missing piece in this puzzle? Is it just a
dream, or we just need someone to put it all together in a weekend
sprint and be forever called a genius?