I have a transactional method and I'd like to call an other method which may throw a RuntimeException.
The problem is that the transaction gets marked as rollbackOnly when the exception is thrown.
The other method call itself is in a try-catch block, but I think the transaction gets marked when the other method returns by throwing an exception.
Example:
MyService.java
@Service
public class MyService {
@Autowired
private MyUtils utils;
@Autowired
private MyCrudRepository repository;
@Transactional
public void publicMethod() {
try {
utils.otherPublicMethod();
} catch (Exception ex) {
ex.printStackTrace();
}
// RollbackException: Transaction marked as rollbackOnly
// Even though I caught the exception from the method call itself
repository.save(new MyEntity());
}
}
MyUtils.java
@Component
public class MyUtils {
// Does not use transactions, repositories
// But I think it inherits the transaction and marks it as rollbackOnly
public void otherPublicMethod() {
// Maybe this is seen as an uncaught exception
throw new RuntimeException();
}
}
Edit:
I don't think this is a duplicate of Does Specifying @Transactional rollbackFor Also Include RuntimeException, because the exception is eventually caught.
The problem may be similar, as it also involves transactions and rollbacks.
Annotation @Transactional
has parameters such as rollbackFor
and no-rollback-for
with which you can say which exceptions will cause or will not cause rollback. For instance you can write:
@Transactional(rollbackFor = {RuntimeException.class})
Which will cause rollback upon RuntimeException
. However, I believe that RuntimeException
causes rollback by default. So you probably have to specify this exception in no-rollback-for
clause.
For details see Transaction Management and look for "16.5.5 settings" paragraph