Question/Issue with ORM transaction implementation

Transactions will NOT work across multiple datasources

I haven't tested it but the way I believe cftransaction handles that
is that it will commit the transaction if the parent transaction
references another datasource. So in your example if you were saving
to two separate datasources all of your object2's would be commited
before it looped to the next object1 if they were going to separate
datasources (and you were nesting your transactions in that pseudo
code). Not a single transaction but there is some handling for that
there....

TLDR; transactions are tricky, we need more control.

.brett

I can't vouch for ORM transactions, but an exception is thrown if you try to
use multiple datasources using cftransaction. I am not aware if that
behaviour is changed in 9.01 but considering backward compatibility, I doubt
that will have changed.

Trust me that was the first thing I did with that psuedo code I presented
earlier, cftransaction doesn't like it.

Regards,
Andrew Scott
http://www.andyscott.id.au/

From: coldbox@googlegroups.com [mailto:coldbox@googlegroups.com] On
Behalf Of Brett
Sent: Saturday, 9 April 2011 12:20 PM
To: ColdBox Platform
Subject: [coldbox:9364] Re: Question/Issue with ORM transaction
implementation

> Transactions will NOT work across multiple datasources

I haven't tested it but the way I believe cftransaction handles that is

that it

will commit the transaction if the parent transaction references another
datasource. So in your example if you were saving to two separate
datasources all of your object2's would be commited before it looped to

the

next object1 if they were going to separate datasources (and you were
nesting your transactions in that pseudo code). Not a single transaction

but

Ok how about this.

One: Defaulting to false for auto transactions.
Two: create another property where you chose the type of transaction:
hibernate or cf. Defaulting to hibernate.

I like changing one to false because the transaction aspect is
available now. Also the type of transaction can be chosen with the
aspect also.

As for savepoints for transactions they are really cool but you need
super control on those especially if you want to rollback to specific
ones. I suggest manual transactions if using savepoints and rollbacks.

As for multiple dsns cftransaction does not support it

I'm all for both of those changes.

.brett

Hey Luis -

I get an error after updating to the latest changes. It's an
interesting case that I am not sure what to think of yet. It might
actually be a "feature" but it may cause confusion because of the
generic it produces.

Here is what I was doing:

I extended the base orm service with my own service. In my service I
have save() method which does some stuff and then call's super.save()
a couple times.

I had decorated my save() with the transaction aspect, and was calling
super.save( transactional = false). After updating it produced the
error:

Error Type: Expression : [N/A]
Error Messages: Element udfPointer is undefined in a CFML structure
referenced as part of an expression.

LINE: 1043
Template: E:\web\sites\cf9.local\webapps\ROOT\coldbox\coldbox-platform
\system\orm\hibernate\BaseORMService.cfc

So what is happening is that getFunctionCalledName() in baseormservice.
$aopWrapper() is returning "udfPointer" not the expected "save"
because the save() method actually get's double wrapped. Once by the
transaction aspect and once by base orm service's init method. I
suspect this will be a larger issue when we start taking advantage of
AOP goodness in the future that that getFunctionCalledName will be
problematic if the function is decorated with any other aspect.

The takeaway is that if you extend the base orm service and implement
one of the transactional methods in your service layer
("save","saveAll","delete","deleteAll","deleteByID","deleteWhere","deleteByQuery")
those will automatically receive the transaction aspect from the base
orm service init() and super.save( transactional=false ) will do
nothing.

Also you might want to wrap the tx.commit() in $aopWrapper in another
check for getUseTransactions() because if my save method in my service
layer changes that property to false, the transaction will still be
committed.

Hope that made sense.

.brett

Ok, I reworked how this worked, The way I had it was also failing on
the use case where inheritance was involved as I was dynamically
changing methods and super scope remains unaffected by coldfusion.
Anyways, I reworked and created proxy methods for all that need
transactions and then just fork accordingly.

Please try now

Great, I'll take a look.

thanks,

.brett