Transactional observers with @Transactional
awestwel Mar 22, 2010 9:06 PMHey All
I am having an issue where the transactional observer fires with a EntityManager persiste but it does not take in to account the commit. In the following example I have wrapped the persist method with @Transactional as show in the example at URL My Link
Based on the @Transactional Interceptor it performs a begin, proceed and commit
@Transactional @Interceptor public class EntityTransactionInterceptor implements Serializable { private @Inject @Any EntityManager em; @AroundInvoke public Object aroundInvoke(InvocationContext ic) throws Exception { boolean act = !em.getTransaction().isActive(); if(act) { em.getTransaction().begin(); } try { Object result = ic.proceed(); if(act) { em.getTransaction().commit(); } return result; } catch (Exception e) { if (act) { em.getTransaction().rollback(); } throw e; } } }
My issue is the following the persistEntityEvent is set to observe during the TransactionPhase.AFTER_SUCCESS. If this means that the event for TransactionPhase.AFTER_SUCCESS does not wait for the commit what happens if the commit fails. Which is exactly what I am seeing. If I try to commit unique values twice it still calls the persistEntityEvent before the commit is executed. This means that the event fires before the final commit which could fail.
@Singleton public class ProductManager { @PersistenceContext EntityManager em; @Inject @Any Event<Product> productEvent; Set<Product> elements = new HashSet<Product>(0); @Transactional public void delete(Product product) { em.delete(product); productEvent.select(new AnnotationLiteral<Deleted>(){}).fire(product); } @Transactional public void persist(Product product) { em.persist(product); productEvent.select(new AnnotationLiteral<Created>(){}).fire(product); } private void persistEntityEvent(@Observes(during=TransactionPhase.AFTER_SUCCESS) @Created Product product) { elements.add(product); } private void deleteEntityEvent(@Observes(during=TransactionPhase.AFTER_SUCCESS) @Deleted Product product) { elements.remove(product); } }
What I want to do is only call the event if the commit executes successfully. Anyone have any ideas on what I am doing wrong?