I have a method like this:
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void doSomeWork(){
Entity = entity = dao.loadEntity();
// do some related work
...
try {
dao.saveEntity(entity);
}
catch(StaleObjectStateException sose){
dao.flush(entity);
doSomeWork();
}
}
I was expecting that by using REQUIRES_NEW transaction propagation and the recursion shown, the StaleObjectStateException would eventually clear but this isn't the case.
How do I recover from this exception?
Turns out there's a bit of a 'gatcha' which I've overlooked...
From spring docs
In proxy mode (which is the default), only 'external' method calls coming in through the proxy will be intercepted. This means that 'self-invocation', i.e. a method within the target object calling some other method of the target object, won't lead to an actual transaction at runtime even if the invoked method is marked with @Transactional!
Because I've been recursing internally, the transaction demarcation wasn't getting applied.
The solution is to recurse via the proxy, like this...
@Autowired
private ApplicationContext applicationContext;
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void doSomeWork(){
Entity = entity = dao.loadEntity();
// do some related work
...
try {
dao.saveEntity(entity);
}
catch(StaleObjectStateException sose){
dao.flush(entity);
applicationContext.getBean(this.getClass()).doSomeWork();
}
}