TransactionInterceptor.java

package org.flasby.transactions;

import jakarta.inject.Inject;
import jakarta.interceptor.AroundInvoke;
import jakarta.interceptor.Interceptor;
import jakarta.interceptor.InvocationContext;
import jakarta.persistence.EntityManager;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.HibernateException;

@Interceptor
@Transactional
@Slf4j
public class TransactionInterceptor {

  @Inject private EntityManagerStoreImpl entityManagerStore;

  @AroundInvoke
  public Object runInTransaction(InvocationContext invocationContext) throws Exception {

    log.debug(">>>>>>>>> runInTransaction {}", invocationContext);
    log.debug("        > runInTransaction {}", invocationContext.getContextData());
    EntityManager em = entityManagerStore.createAndRegister();

    Object result = null;
    try {
      em.getTransaction().begin();

      result = invocationContext.proceed();

      em.getTransaction().commit();
      log.debug("<<<<<<<<< Commited transaction");

    } catch (Exception e) {
      try {
        if (em.getTransaction().isActive()) {
          em.getTransaction().rollback();
          log.info("Rolled back transaction: {}", e.getMessage());
        }
      } catch (HibernateException e1) {
        log.error("Rollback of transaction failed -> " + e1);
      }
      throw e;
    } finally {
      if (em != null) {
        entityManagerStore.unregister(em);
        em.close();
      }
    }

    return result;
  }
}