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
JdbcLockRegistry is unable to retry a lock when there is a serialization problem and you are using JPATransactionManager instead of DataSourceTransactionManager #3733
Comments
How about to treat that See also this thread: #3613 |
What do you mean with treat them equal? which part of the code/process are you referring to?
Really? I checked the DataSourceTransactionManager code and they handle directly the SQLException, which I think is the problem here, as Hibernate is throwing a TransactionException instead. |
I mean this:
That's because I see that Yeah... I see what you mean about that At the same time: how about to have a custom |
Yeah, the |
We decided to go for the following solution: overriding the DefaultLockRepository to handle a different TransactionManager. By default, using DataSourceTransactionManager catches well the serializable exception, however, the DefaultLockRepository grabs the transaction manager from the Spring context, there is not an easy way to override it, so, we do the following: First, override the DefaultLockRepository class, as follows:
There, we explicitly set which transaction manager we want to use for the lock. Second, we create the
We think this is less invasive than overriding the HibernateJpaDialect. |
I think that's the one of those reasons why we have a I think as an out-of-the-box fix we may reconsider those If you agree, we may reopen the issue and proceed with the possible, flexible solution. |
That sounds great, reopening the issue |
Fixes spring-projects#3733 The `@Transactional` resolves a primary `TransactionManager` bean from the application context which might not be sufficient for all the use-case. To make it work with the custom (or specific) `TransactionManager` we have to extend a `DefaultLockRepository` and override all those `@Transactional` method * Change the logic of the `DefaultLockRepository` from `@Transactional` to the `TransactionTemplate` and use provided `TransactionManager` or resolve one from the application context * Adjust tests to use explicit `TransactionManager` and call `afterSingletonsInstantiated()` to initialize a default `TransactionTemplate` * Mention the change in the docs
* GH-3733 Configure TxManager for DefLockRepository Fixes #3733 The `@Transactional` resolves a primary `TransactionManager` bean from the application context which might not be sufficient for all the use-case. To make it work with the custom (or specific) `TransactionManager` we have to extend a `DefaultLockRepository` and override all those `@Transactional` method * Change the logic of the `DefaultLockRepository` from `@Transactional` to the `TransactionTemplate` and use provided `TransactionManager` or resolve one from the application context * Adjust tests to use explicit `TransactionManager` and call `afterSingletonsInstantiated()` to initialize a default `TransactionTemplate` * Mention the change in the docs * * Extracted all the `TransactionTemplate`s to the properties for caching * Add `BeanInitializationException` for no-unique `PlatformTransactionManager` bean in the `afterSingletonsInstantiated()` * Fix language in the exception message Co-authored-by: Gary Russell <grussell@vmware.com> Co-authored-by: Gary Russell <grussell@vmware.com>
I still have this problem with 'org.springframework.integration:spring-integration-jdbc:5.5.16' |
Was it fixed in version 6? |
This was a breaking change, therefore it didn't make it into |
Thanks |
In what version(s) of Spring Integration are you seeing this issue?
Spring boot version: 2.6.2
Spring data jpa: 2.6.0
Spring Integration version: 5.5.6
Describe the bug
JdbcLockRegistry
is unable to retry a lock when there is a serialization problem and you are usingJPATransactionManager
instead ofDataSourceTransactionManager
.As I have an application that uses the
JdbcLockRegistry
and JPA with Hibernate, by default, the application usesJPATransactionManager
, but seems like for some transactional errors,JdbcLockRegistry
is unable to retry the lock, as you can see in the following stack trace:As far as I can tell, seems like to retry a lock we expect the following exceptions to be thrown, as you can see here:
However, Hibernate is throwing a
org.hibernate.TransactionException
, and after wrapped in theJpaSystemException
, which is not part of any of the previous exceptions hierarchy, and therefore, the retry is not applied. I created this bug on the Hibernate side as I think we might not have a lot of options in Spring side.Now, regarding workarounds, I can tell the following:
JPATransactionManager
to catch this particular error and throw the right exception, likeorg.springframework.dao.CannotAcquireLockException
, which is aTransientDataAccessException
. This stack overflow question shows how. This solution seems pretty fragile.XXXXXLockRespository
, which inherit fromDefaultLockRepository
, and override the@Transactional
annotation to explicitly tell which transaction manager to use, and declare a newDataSourceTransactionManager
only to be used for the newXXXXXLockRepository
.Not sure if we have more options.
To Reproduce
Use a
JPATransactionManager
instead ofDataSourceTransactionManager
forJdbcLockRegistry
, and generating a serialization database error.Expected behavior
JdbcLockRegistry
should work withJPATransactionManager
andDataSourceTransactionManager
The text was updated successfully, but these errors were encountered: