Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JtaTransactionManager does not translate exceptions like JpaTransactionManager [SPR-9053] #13692

Closed
spring-issuemaster opened this issue Jan 24, 2012 · 5 comments

Comments

@spring-issuemaster
Copy link
Collaborator

@spring-issuemaster spring-issuemaster commented Jan 24, 2012

dodo bird opened SPR-9053 and commented

The JpaTransactionManager seems to have a nice piece of functionality that translates an exception thrown by Hibernate.

For example it will call translateExceptionIfPossible in doCommit and we will get a specific exception somewhere in the org.springframework.dao.DataAccessException hierarchy.
For example org.hibernate.StaleStateException will get wrapped into a JpaOptimisticLockingFailureException.

The JtaTransactionManger has no such call and seems to bundle all of my Hibernate exceptions into UnexpectedRollbackException exception.

Not sure if this is a bug but it seems inconsistent and also we lose all of the specific exception type information.


Affects: 3.1 GA

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Feb 7, 2012

Juergen Hoeller commented

I'm afraid that this comes as a consequence of the design of JTA as well as JPA: There is no separate flush step before commit in JPA, so flushing always happens as part of the canonical commit call - which in this case comes from JTA. And with JTA, it really is the JTA provider dealing with underlying synchronization exceptions, deciding to dumb them down into the JTA exception hierarchy...

We could theoretically unwrap JTA exceptions and try to find native JPA exceptions underneath, but unfortunately there is no proper contract for this. A JTA provider is not even required to preserve the original exception at all - and could in practice wrap a native exception in any number of its own provider exceptions.

Juergen

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Feb 7, 2012

Juergen Hoeller commented

One way around this is to explicitly flush the EntityManager in a repository bean and catch the JPA OptimisticLockException right on the spot there - before commit. When using persistence exception translation, a bean higher up the call stack (which calls into the repository bean through a proxy) could even catch Spring's translated OptimisticLockingFailureException that way.

Juergen

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Mar 5, 2012

dodo bird commented

Hi Juergen, thanks for reading and the comments.

To clear up here is the exception chain (nested cause exceptions) I am seeing on a hibernate stale state exception with JtaTransactionManger:

org.springframework.transaction.UnexpectedRollbackException.class,
javax.transaction.RollbackException.class,
javax.persistence.OptimisticLockException.class,
org.hibernate.StaleStateException.class

I still don't understand why it is not possible to translate the underlying exception type with JTA. (The JPA manager seems to do exactly that).

In simplest terms it means: We are in some java function and we get an exception thrown at us, we wrap it and throw it again.

Is there some uncertainty about which underlying exceptions we are getting from the underlying layers when we are the JTA manager?

Also I don't understand when you say 'unwrap JTA exceptions'. The JTA manager is a Spring class and it is deciding itself what exception to throw. It would not need to unwrap anything but only look at what exception it got.

Thanks in advance.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Mar 5, 2012

dodo bird commented

The code I am referring to is org.springframework.transaction.jta.JtaTransactionManager

the method is

protected void doCommit(DefaultTransactionStatus status)

try {

// some commit logic...

...
txObject.getUserTransaction().commit();
}
catch (RollbackException ex) {
throw new UnexpectedRollbackException(
"JTA transaction unexpectedly rolled back (maybe due to a timeout)", ex);
}
catch (HeuristicMixedException ex) {
throw new HeuristicCompletionException(HeuristicCompletionException.STATE_MIXED, ex);
}
catch (HeuristicRollbackException ex) {
throw new HeuristicCompletionException(HeuristicCompletionException.STATE_ROLLED_BACK, ex);
}
catch (IllegalStateException ex) {
throw new TransactionSystemException("Unexpected internal transaction state", ex);
}
catch (SystemException ex) {
throw new TransactionSystemException("JTA failure on commit", ex);
}

Are you saying its already too late at that point to translate because we have lost/not gotten some information ? Or could we decide to place the exception in a hierarchy at this point ?

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Jan 12, 2019

Bulk closing outdated, unresolved issues. Please, reopen if still relevant.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.