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?