Use Java 17 and above.
Reliably reproduce concurrent transactions scenario in developer test.
Get version of existing record, increment it by one and save. Multiple transactions will try to do the same. If we successfully manage to co-ordinate the transactions to read the same version and increment it by one, then we have successfully reproduced the scenario.
We used intellij idea's test configuration to repeat test until failure.
For expected failure scenarios, tests failed within 1000 iterations. If it is taking too long, maybe stop and retry before your intellij hangs up. Or suggest us a better method.
Transaction hook can help you gain visibility inside the transaction stages.
Example:
TransactionSynchronizationManager.registerSynchronization(
new TransactionSynchronization() {
@Override
public void beforeCommit(boolean readOnly) {
System.out.println(Thread.currentThread().getName() + " beforeCommit");
}
});