Reputation: 395
I have a scenario as below
methodA(){
try{
objB.methodB();
}
catch(Exception ex){
log(exception caught);
}
@Transactional(value = "txManager", propagation = Propagation.REQUIRES_NEW,rollbackFor={Exception.class, StaleObjectStateException.class})
methodB(){
methodC();
}
@Transactional(value = "txManager", propagation = Propagation.REQUIRED, rollbackFor = {Exception.class,StaleObjectStateException.class})
methodC(){
/*Some logic that throws HOLF/SOSE exception. Essentially calling merge on entity that has @Version enabled
}
My issue is, for a given flow i may have two request calling this method at same time. I expect methodC to throw exception for Optimistic locking failure and transaction to be rolled back.
My Expectation was:
Lets say i have two requests R1 and R2 R1 and R2 call methodA ->methodB (Starts a new transaction) ->methodC(transaction propogated) : both read same entity version, both make same changes and call merge -> methodC completes flow back to methodB -> methodB completes forcing transaction to commit-> transaction commit calls session.flush , gets run time exception for optimistic locking and is rolled back.
I do get the SOSE exception in method A , i can see it in my loggers but the transaction is committed and both the records are getting persisted.
Whats happening is as below: R1 and R2 call methodA ->methodB (Starts a new transaction) ->methodC(transaction propogated) : both read same entity version, both make same changes and call merge -> methodC completes flow back to methodB -> methodB completes forcing transaction to commit-> transaction commits -> throws run time exception for optimistic locking DOESN'T roll back and exception is caught by methodA.
If i explicitly throw an exception in methodC, transaction does get rolled back.
I am not sure why its not rolling back the transaction when the Optimisitc lock failure exception is thrown.
Please advise
Upvotes: 0
Views: 442
Reputation: 395
Ok.. So i seems to have it working. Turns out the issue is with JTA provider. I was deploying the code on Tomee this will ensure Spring picks the provider from tomcat lib and it was using Gerenimo which seems to be not handling roll back. I pushed the same code on weblogic and used org.hibernate.service.jta.platform.internal.WeblogicJtaPlatform as JTA provider, this seems to be working as expected. Will post if i get the reason why Gerenimo was not working or if there is something i am missing on it.
Upvotes: 1