Reputation: 5345
I'm using Spring 3.0.5, Hibernate 3.6.7 and Atomikos Transactionessentials 3.7.0. Transactions configured using AOP in applicationContext.xml. Everything just works fine. (commit, rollback)
My intention is to throw a specific exception inside of a jta-transaction. This way the transaction should be rolled back and I get some detailed information about the cause of the rollback.
The problem is, that the only exception I can catch is a rollback-transaction thrown by atomikos, telling me, that the transaction was unexpectedly rolled back.
How can I get my own exception outside the transaction?
Here is a small example, because I don't know if my explanation was good enough. This is only for demonstration what my intention is. Please don't comment any typos.
A specific exception (might be some standard exception as well):
public class MySpecialException extends Exception {
public MySpecialException(String someInfo) {
super(someInfo);
}
}
An interface declareing a method which declares to throw the exception:
public interface MyInterface {
Object someJtaTransactionMethod(String param) throws MySpecialException;
}
A class implementing the interface:
public class MyClass implements MyInterface {
Object someJtaTransactionMethod(String param) throws MySpecialException {
// some operations with some errorstate detected
// so throw the exception:
throw new MySpecialException("Things went terribly wrong!");
// some other code
}
}
And some code that calls the function and catches the exceptions.
public class Caller {
@Autowired
private MyInterface callee;
public void test() {
try {
callee.someJtaTransactionMethod("Some test");
} catch (MySpecialException mex) {
// I want to get here
} catch (Exception ex) {
// but I only get here
}
}
}
Is this possible at all?
UPDATE: Of course I had a look at the exception cause. The exception itself is of org.springframework.transaction.UnexpectedRollbackException. The cause is of class javax.transaction.RollbackTransaction and has a cause com.atomikos.icatch.RollbackException.
I think what happens is, that atomikos notices the exception and performs a rollback (as desired), but then atomikos (maybe other jta-implementations as well) throws an exception indicating that the transaction was rolled back (unexpectedly) and my exception is gone.
UPDATE 2: Funny thing is, that if I haven't done anything that has to be rolledback, I can catch my exception as desired!
UPDATE 3 and SOLUTION: JB Nizet pointed me to the solution. In fact my transaction wasN#t rolled back as I suspected, but because of the reason for me to throw my exception, I got an contraint violation and thus atomikos threw its exception on commit. Now that I configured my transaction to rollback for my exceptions everything works as expected and desired.
Upvotes: 3
Views: 4090
Reputation: 691785
Is your exception a runtime exception or a checked exception?
Spring rollbacks by default if a runtime exception is thrown, and commits by default if a checked exception is thrown.
From the stack trace, it seems that your exception is a checked exception, so Spring tries to commit, but can't because the JTA TM (Atomikos) refuses to commit (because of a timeout, for example).
So, if you want this exception to cause a rollback, make it a runtime exception or declare it in the rollbackFor
attribute of the @Transactional annotation. If it must not cause a rollback, then try to discover why Atomikos refuses to commit (too short timeout, something else... the logs could help).
Upvotes: 5
Reputation: 2051
Looks like a type to me as you throw a MySpecialException that inherits from Exception instead of MyException?
Otherwise catch MySpecialException instead of MyException.
Upvotes: 0