I can't manage to prevent a transaction from rolling back after a RuntimeException
.
My env is Spring 4.1 + Hibernate 3.6 + JTA (WebSphereUowTransactionManager) running on Websphere 8.0.
"doStuff" case: works
First off, a simple case that behaves as expected. Since I catch the RuntimeException, the transaction commits and the new resource is created successfully.
@Service("fooService")
public class FooServiceImpl implements IFooService {
@Transactional
@Override
public void doStuff(Resource res){
authService.createResource(res, "ADMIN");
try {
throw new RuntimeException("SOMETHING");
} catch (RuntimeException e) {
e.printStackTrace();
}
}
"doStuff2" case: works
The next one is OK as well. I declare the noRollbackFor and it let's the transaction commit:
@Transactional(noRollbackFor=RuntimeException.class)
@Override
public void doStuff2(Resource res){
authService.createResource(res, "ADMIN");
throw new RuntimeException("SOMETHING");
}
"doStuff12" case: does NOT work
And finally the problematic one. The difference is that in this case the exception is raised by the second call to authService.createResource
. FYI, authService.createResource
is only marked as @Transactional
, so the default Propagation configuration applies and it should be joining the calling service's transaction.
@Transactional(noRollbackFor=RuntimeException.class)
@Override
public void doStuff12(Resource res){
authService.createResource(res, "ADMIN");
try{
res.setName("EXISTING-RESOURCE");
authService.createResource(res, "ADMIN");
}catch(RuntimeException e){
e.printStackTrace();
}
}
Despite catching the RuntimeException and declaring the noRollbackFor attribute the transaction always rolls back. Any explanation??
Log trace info:
org.springframework.transaction.jta.WebSphereUowTransactionManager DEBUG - Creating new transaction with name [null]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; '',+com.myorg.webapps.exception.ElementoYaExistente
org.springframework.transaction.jta.WebSphereUowTransactionManager DEBUG - Invoking WebSphere UOW action: type=1, join=false
org.springframework.transaction.support.TransactionSynchronizationManager TRACE - Initializing transaction synchronization
org.springframework.transaction.interceptor.TransactionInterceptor TRACE - Getting transaction for [com.myorg.test.service.impl.FooServiceImpl.doStuff12]
org.springframework.transaction.jta.WebSphereUowTransactionManager DEBUG - Creating new transaction with name [null]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
org.springframework.transaction.jta.WebSphereUowTransactionManager DEBUG - Invoking WebSphere UOW action: type=1, join=true
org.springframework.transaction.interceptor.TransactionInterceptor TRACE - Getting transaction for [com.myorg.authmgr.service.impl.AuthorizationServiceImpl.createResource]
org.springframework.transaction.jta.WebSphereUowTransactionManager DEBUG - Returned from WebSphere UOW action: type=1, join=true
org.springframework.transaction.jta.WebSphereUowTransactionManager DEBUG - Creating new transaction with name [null]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
org.springframework.transaction.jta.WebSphereUowTransactionManager DEBUG - Invoking WebSphere UOW action: type=1, join=true
org.springframework.transaction.interceptor.TransactionInterceptor TRACE - Getting transaction for [com.myorg.authmgr.service.impl.AuthorizationServiceImpl.createResource]
org.springframework.transaction.interceptor.RuleBasedTransactionAttribute TRACE - Applying rules to determine whether transaction should rollback on java.lang.Runtime: Couldn't create the resource, it already exists: EXISTING-RESOURCE
org.springframework.transaction.interceptor.RuleBasedTransactionAttribute TRACE - Winning rollback rule is: null
org.springframework.transaction.interceptor.RuleBasedTransactionAttribute TRACE - No relevant rollback rule found: applying default rules
org.springframework.transaction.jta.WebSphereUowTransactionManager DEBUG - Returned from WebSphere UOW action: type=1, join=true
org.springframework.transaction.jta.WebSphereUowTransactionManager TRACE - Triggering beforeCommit synchronization
org.springframework.transaction.jta.WebSphereUowTransactionManager TRACE - Triggering beforeCompletion synchronization
org.springframework.transaction.support.TransactionSynchronizationManager TRACE - Clearing transaction synchronization
org.springframework.transaction.jta.WebSphereUowTransactionManager DEBUG - Returned from WebSphere UOW action: type=1, join=false
noRollbackFor=RuntimeException.class
rule. For me it would be more logical that it adhered to the configuration of the whole transactional scope... In this case, the inner method MUST be transactional and MUST rollback when called on its own so I have to rule out the two first suggestions. About the third one, Spring is sort of forcing us to offer two implementations, one transactional, one not transactional, in our APIs to manage this (not so uncommon) situations, which unelegant – Desantis