Reputation: 10918
We're building a REST service with Spring and JPA where each method is annotated @Transactional
, since one REST call is one transaction. Now if say a user is trying to call delete on a resource that has dependencies, hibernate will throw a PersistenceException
, causing the REST server call to return with status 500.
We want to catch those exceptions and wrap them in our own error object, that will contain custom error codes as well as the orignial message.
I tried just plain catching all RuntimeExceptions
in the REST call and then returning our custom error object. That however won't work, as appearently the fact that the transaction has been aborted will get handled outside my method.
I also tried to catch the PersistenceException
directly at DAO level. This worked fine in my unit tests didn't change anything outside them. Also our web container seems to just do its own thing by throwing a DataIntegrityViolationException
instead of a PersistenceException
. That doesn't even appear in the trace. As a side note, that's rather confusing, as I thought Hibernate would take care of its own stuff. Why is spring interfering?
Well anyway.. I also tried to use
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
inside the REST service method with no success.
I'm at a loss here.. It seems error handling for a transaction started by @Transactional
is just out of my hands..?! Is it maybe because the annotation creates a proxy that gets processed in a different scope?
Is the only option to handle transactions manually with the TransactionTemplate
?
Upvotes: 1
Views: 1709
Reputation: 120771
I expect that the exception will be thrown when one tries to commit the transaction. So you will not get the exception as long as you are inside of the transaction.
Spring will do something called Exception-Translation, this will "translate" some (vendor) specific exceptions into some other Spring Exceptions. I think this is the reason why you will notice the DataIntegrityViolationException
Upvotes: 4