Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Transaction : rollbackfor and norollbackfor both defined

Here is the problem I got in an application I have to maintain:

I have a first class with the annotation @Transactional(rollbackFor = CustomExceptionA.class) Then in the following code I call a method of @Transactional(noRollbackFor = CustomExceptionB.class) NB : CustomExceptionA or CustomExceptionB have only one common ancestor which is Exception.

And of course, when I execute the code an exception is raised which is neither of type CustomExceptionA or CustomExceptionB nor does it subclasses them.

So the question is simple:
What happens to the transaction in that case? Does it commit? Does it rollback? Does it hold on an unfinished state waiting for the application to do something (which is actually an answer that might explain some ugly things seen in this application)? and moreover: why?

like image 847
benzonico Avatar asked Aug 13 '13 08:08

benzonico


People also ask

What is @transactional rollbackFor exception class?

The @Transactional annotation makes use of the attributes rollbackFor or rollbackForClassName to rollback the transactions, and the attributes noRollbackFor or noRollbackForClassName to avoid rollback on listed exceptions. The default rollback behavior in the declarative approach will rollback on runtime exceptions.

Can we use @transactional at class level?

This is because @Transactional does not work when calling a method from within the same class. It would work if you would call method2() from another class. In proxy mode (which is the default), only external method calls coming in through the proxy are intercepted.

Does @transactional throw exception?

@Transactional only rolls back transactions for unchecked exceptions. For checked exceptions and their subclasses, it commits data. So although an exception is raised here, because it's a checked exception, Spring ignores it and commits the data to the database, making the system inconsistent.

On which can the @transactional annotation be applied?

You certainly can place the @Transactional annotation on an interface (or an interface method), but this works only as you would expect it to if you are using interface-based proxies.


1 Answers

Spring Framework's transaction infrastructure code will, by default, only mark a transaction for rollback in the case of runtime, unchecked exceptions; that is, when the thrown exception is an instance or subclass of RuntimeException. (Errors will also - by default - result in a rollback.) Checked exceptions that are thrown from a transactional method will not result in the transaction being rolled back.

Why? That makes a perfect sense: checked exceptions are mandatory for handling or throwing out, so if you're throwing the checked exception out of the transactional method, then framework supposes you know what you're doing. In case of unchecled exceptionit's likely to be a bug, or exception handling flaw, so transaction is rolled back to avoid data corruption.

like image 94
Jk1 Avatar answered Oct 07 '22 08:10

Jk1