I'm using grails 1.3.7 together with Oracle 11g and trying to manage inner transactions. I have a bean Person that is passed to a transactional (Propagation.REQUIRED) service method who makes some modification. Then it is passed to another transactional (propagation = Propagation.REQUIRES_NEW) method that makes some other modification and then throws an Exception. What I expected to see is the rollback of all the modification of the second service but still valid those of the first one. This is the situation:
//outer transaction
class MyService {
def nestedService
@Transactional(propagation = Propagation.REQUIRED)
public void testRequiredWithError(Person person) {
person.name = 'Mark'
try {
nestedService.testRequiresNewWithError(person)
} catch (RuntimeException e) {
println person.age //this prints 15
println e
}
}
}//end MyService
//inner transaction
class NestedService{
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void testRequiresNewWithError(Person person) {
person.age = 15 //expected after Exception will be discarded
throw new RuntimeException("Rollback this transaction!")
}
}
then I run grails console and check on the DB after it ends. ...
def p = Person.get(671)
def myService = ctx.myService
println p.name //'John'...from DB
println p.age //25...from DB
myService .testRequiredWithError(p)
println p.name // 'Mark'....correct
println p.age // 15....UNEXPECTED..
//same result checking on the DB after console ends and transaction flushes
I tried to use Propagation.NESTED after activating it in the bootstrap by transactionManager.setNestedTransactionAllowed(true)
and use savepoints like in this post
grails transaction set savepoint
but still got same result.
What am I missing????
Thank you in advance.
I'd test for
p.isAttached()
as transaction rollback detaches the domain object from the Hibernate session. Also in the test I'd reload the domain object from database - effectivelyp = Person.get(671)
again to reload data from database.I think the reason the
age
property is set to 15 after the test is that after the exception the domain object and the database are out of sync (and the domain object is detached).For more see: https://weblogs.java.net/blog/blog/davidvc/archive2007/04/jpa_and_rollbac.html