Grails Transactions using @Transactional annotations and Propagation.REQUIRES_NEW

30 / Jul / 2010 by Abhishek Tejpaul 5 comments

Hi All,

Here is how you can implement a new transaction in an already executing transaction in Grails which uses nothing but Spring framework’s Transaction mechanism as an underlying implementation. Spring provides @Transactional annotations to provide declarative transactions. We can use the same in our Grails project to achieve the transactional behavior.

Here is the scenario: You have two domain classes named SecuredAccount and AccountCreationAttempt. You try to transactionally save the SecuredAccount object which in turn creates a AccountCreationAttempt object which writes to the database stating: “There is an attempt to create a new SecuredAccount at this time: <current date and time>”. Point to note here is that even if the creation of the new SecuredAccount object fails, the record must still be written to the database so that the Administrator can validate whether the attempt at the specific time was by a legitimate user or an attacker.

Here is the code:

import org.springframework.transaction.annotation.*
Class MyService {

static transactional = false
def anotherService

def createSecuredAccount() {
def securedAccount = new SecuredAccount(userId:"John")
throw new RuntimeException("Error thrown in createSecuredAccount()")
import org.springframework.transaction.annotation.*
class AnotherService {

static transactional = false

@Transactional(propagation = Propagation.REQUIRES_NEW)
def createAccountCreationAttempt() {
def accountCreationAttempt = new AccountCreationAttempt(logRemarks: "There is an attempt to create a new SecuredAccount at this time: {new Date()}")

Now in this scenario, AccountCreationAttempt object always gets persisted whether or not the transaction for creating SecuredAccount object fails.

Here are few gotchas regarding the above transactions:

1.) First of all, for Propagation.REQUIRES_NEW to work as intended, it has to be inside a new object i.e. a new service in our example. If we had put the createAccountCreationAttempt() method in the MyService there would be no new transaction spawned and even no log entry would be made. This is Spring’s proxy object implementation of transactions and you can read more about it here:

Please pay special attention to the “NOTE” sub-section.This is what it states:

“In proxy mode (which is the default), only external method calls coming in through the proxy are intercepted. This means that self-invocation, in effect, a method within the target object calling another method of the target object, will not lead to an actual transaction at runtime even if the invoked method is marked with @Transactional.”

2.) Secondly, all the @Transactional methods should have a public visibility i.e. createSecuredAccount() and createAccountCreationAttempt() methods should be public methods, and not private or protected. This again is Spring’s @Transactional annotations implementation and you can read about it at the same link as provided above. Note the right side-bar titled “Method visibility and @Transactional“.

Well, once you keep note of these gotchas I guess you are all set to make good use of @Transactional annotations and its full power.

Cheers !!!

– Abhishek Tejpaul
[IntelliGrape Software Pvt. Ltd.]


comments (5)

  1. Doretta

    I am not genuinely sure if greatest practices have emerged around things like that, but I am sure that your wonderful job is clearly identified. I was thinking if you offer any membership to your RSS feeds as I would be very interested but i can’t find any link to register here.Where is it? Best wishes, Doretta.

  2. Jasmine

    This blog is certainly rather handy because I am currently building an internet flower blog – however I’m in the beginning stages therefore it is really quite small, nothing like this site. It would be great if I could link to a few of the threads because they’re very intriguing. Many thanks. Claire Garcia


Leave a Reply

Your email address will not be published. Required fields are marked *