5.4.5.5. Transaction Listeners
Transaction listeners are designed to react on transaction lifecycle events. Unlike entity listeners, they are not tied to an entity type and invoked for each transaction.
A listener is a managed bean implementing one or both BeforeCommitTransactionListener and AfterCompleteTransactionListener interfaces.
- BeforeCommitTransactionListener
-
beforeCommit()method is called before transaction commit after all entity listeners if the transaction is not read-only. The method accepts a current EntityManager and a collection of entities in the current persistence context.The listener can be used to enforce complex business rules involving multiple entities. In the following example, the
amountattribute of theOrderentity must be calculated based ondiscountvalue located in the order, andpriceandquantityofOrderLineentities constituted the order.@Component("demo_OrdersTransactionListener") public class OrdersTransactionListener implements BeforeCommitTransactionListener { @Inject private PersistenceTools persistenceTools; @Override public void beforeCommit(EntityManager entityManager, Collection<Entity> managedEntities) { // gather all orders affected by changes in the current transaction Set<Order> affectedOrders = new HashSet<>(); for (Entity entity : managedEntities) { // skip not modified entities if (!persistenceTools.isDirty(entity)) continue; if (entity instanceof Order) affectedOrders.add((Order) entity); else if (entity instanceof OrderLine) { Order order = ((OrderLine) entity).getOrder(); // a reference can be detached, so merge it into current persistence context affectedOrders.add(entityManager.merge(order)); } } // calculate amount for each affected order by its lines and discount for (Order order : affectedOrders) { BigDecimal amount = BigDecimal.ZERO; for (OrderLine orderLine : order.getOrderLines()) { if (!orderLine.isDeleted()) { amount = amount.add(orderLine.getPrice().multiply(orderLine.getQuantity())); } } BigDecimal discount = order.getDiscount().divide(BigDecimal.valueOf(100), 2, BigDecimal.ROUND_DOWN); order.setAmount(amount.subtract(amount.multiply(discount))); } } } - AfterCompleteTransactionListener
-
afterComplete()method is called after transaction is completed. The method accepts a parameter indicating whether the transaction was successfully committed and a collection of detached entities contained in the persistence context of the completed transaction.Usage example:
@Component("demo_OrdersTransactionListener") public class OrdersTransactionListener implements AfterCompleteTransactionListener { private Logger log = LoggerFactory.getLogger(OrdersTransactionListener.class); @Override public void afterComplete(boolean committed, Collection<Entity> detachedEntities) { if (!committed) return; for (Entity entity : detachedEntities) { if (entity instanceof Order) { log.info("Order: " + entity); } } } }