I'm looking for a way to have Spring bind a new entityManager in the EntityManagerHolder for methods marked @Transactional( propagation = Propagation.REQUIRES_NEW ) suspending the existing one if it exists. I'm also surprised that this isn't the default behavior. Let me explain why:
First my general setup: I'm using the OpenEntityManagerInViewFilter to make an entityManager available throughout a request. Controller methods that save changes are marked @Transactional( REQUIRED ). These methods cause the entityManager opened by the filter to by associated to the transaction, so that when the transaction commits, the entityManager is flushed, but stays around for the rest of the request. Everything is as expected.
Now comes the problem. I have an exception handler setup to log unexpected errors that occur in controller methods to the database. Here's it is:
The problem is that the @Transactional( REQUIRES_NEW ) doesn't cause a new entityManager to be created, but rather uses the entityManager opened by the filter just like @Transactional( REQUIRED ). Here's a use case when this fails to work properly:Code:@Transactional( propagation = Propagation.REQUIRES_NEW ) public void write( Throwable t, String externalId ) { SystemLog sl = new SystemLog(); sl.setExternalId( externalId ); sl.setSummary( t.getMessage() ); sl.setDetail( ExceptionUtils.getFullStackTrace( t ) ); sl.setTimestamp( new Date() ); systemLogDao.persist( sl ); }
1 - the controller method (REQUIRED) persists an invalid entity
2 - the commit causes a validation exception to be thrown, the transaction is rolled back.Code:@Transactional public String save() { Company co = companyModel.getCompany(); co.setCompanyName( " " ); // this value causes entity validation to fail on commit companyDao.merge( co ); return "saved"; }
3 - the exception handler is called because of this (REQUIRES_NEW), and persists an entity about the error.
4 - the exception handler's transaction commits, but since it's using the same entityManager, which still contains the invalid entity, it also causes a validation exception to be thrown, and is also rolled back!
It seems I really should be getting a new entityManager when propagation = REQUIRES_NEW! Is there some way to tell Spring to behave like this or some other way (preferably not a hack, I got that covered already!) to accomplish what I want?


Reply With Quote