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

Rollback of transaction participating in nested transaction should not enforce rollback of global transaction [SPR-6568] #11234

Closed
spring-projects-issues opened this issue Dec 16, 2009 · 7 comments
Assignees
Labels
in: data Issues in data modules (jdbc, orm, oxm, tx) type: enhancement A general enhancement
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

spring-projects-issues commented Dec 16, 2009

Clemens Schneider opened SPR-6568 and commented

In my scenario, I have a global transaction (PROPAGATION_REQUIRED) in which I start a nested transaction (PROPAGATION_NESTED) in which I start another transaction (PROPAGATION_REQUIRED). A RuntimeException is thrown inside the most inner transaction and is caught inside the most outer transaction. Now I would expect that only the most inner and the nested transaction get rolled back to its savepoints but instead the whole transaction gets marked as rollbackOnly which gets me an UnexpectedRollbackException.
A fix would be to set the globalRollbackOnParticipationFailure flag of the platform transaction manager to false, but in general, this behaviour is desired in our application.
Wouldn't it be possible somehow to check in the inner transaction if there is another nested transaction active and if this is the case, to not mark the transaction as rollbackOnly?

Simply put:
PROPAGATION_REQUIRED {
try {
PROPAGATION_NESTED {
PROPAGATION_REQUIRED {
throws RuntimeException(); // causes whole transaction to rollback
}
}
} catch (RuntimeException) {
// handle here without re-throwing
}
}


Affects: 2.5.5

Issue Links:

Referenced from: commits 0f51ff5

3 votes, 5 watchers

@spring-projects-issues
Copy link
Collaborator Author

jean commented

Was is the status with Spring 3.x??
We seem to have the same problem.

@spring-projects-issues
Copy link
Collaborator Author

Clemens Schneider commented

You could vote on the issue.

@spring-projects-issues
Copy link
Collaborator Author

Stéphane Nicoll commented

which transaction manager are you using?

You should use Propagation.REQUIRES_NEW instead. The Nested propagation type has some limitations as explained in the javadoc:

Note: Actual creation of a nested transaction will only work on specific transaction managers. Out of the box, this only applies to the JDBC DataSourceTransactionManager when working on a JDBC 3.0 driver. Some JTA providers might support nested transactions as well.

My best guess at this point is that you are facing those limitations which explains why you're not getting the proper transaction boundaries you'd expect

@spring-projects-issues
Copy link
Collaborator Author

Clemens Schneider commented

The underlying transaction-manager was indeed a DataSource-based one.

@spring-projects-issues
Copy link
Collaborator Author

siedlp01 commented

I'm facing the same issue at the moment.

My scenario is the outer transaction boundary has a propagation of PROPAGATION_REQUIRED which causes the transaction to be started.

In this transaction I am processing several tasks. If an error should occur during a single task, I do not want the whole transaction to be rolled back, therefore I wrap the task processing in another transaction boundary with a propagation of PROPAGATION_NESTED.

Everything works as expected if a runtime exception is thrown from inside the nested transaction. The nested transaction is rolled-back to the save-point, and processing can continue to the next task.

The problem comes when, during task processing, calls are made to existing service methods defined with a transaction boundary of PROPAGATION_REQUIRED. Any runtime exceptions thrown from these methods cause the underlying connection to be marked as rollback-only, rather than respecting the current parent transaction nested propagation.

The result is that the nested transaction is rolled-back to the save-point, but the existing outer transaction can never be committed.

It seems to make more sense to me that rolling back on exception from a PROPAGATION_REQUIRED transactional boundary should respect the propagation of any pre-existing parental transactional contexts.

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

Indeed, this is unintuitive. While setting globalRollbackOnParticipationFailure to false is a way out at the moment, we should accept such a REQUIRED-within-NESTED case by default and consider a rollback to a savepoint as a sufficient for the nested REQUIRED rollback intent.

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

As of Spring Framework 5.0, nested transactions resolve their rollback-only status on a rollback to a savepoint, not applying it to the global transaction anymore. This required some subtle refinements in AbstractPlatformTransactionManager and co, in particular for setRollbackOnly cases without an exception where we do not allow for unnoticed rollbacks, but should be more intuitive overall now.

On older versions, the recommended workaround is to switch globalRollbackOnParticipationFailure to false in such scenarios.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: data Issues in data modules (jdbc, orm, oxm, tx) type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

2 participants