7.10.2. Transactional Observers

트랜잭션 관찰자는 이벤트가 발생한 트랜잭션의 완료 단계 전후에 이벤트 알림을 받습니다. 상태 저장 개체 모델에서는 종종 상태가 단일 원자 트랜잭션보다 긴 동안 유지되기 때문에 트랜잭션 관찰자가 중요합니다.

트랜잭션 관찰자는 5가지가 있습니다.

  • IN_PROGRESS: 기본적으로 관찰자는 즉시 호출됩니다.
  • AFTER_SUCCESS: 관찰자는 트랜잭션 완료 단계 이후에 호출되지만 트랜잭션이 성공적으로 완료된 경우에만 호출됩니다.
  • AFTER_FAILURE: 트랜잭션 완료 단계 후에 관찰 프로그램이 호출되지만 트랜잭션이 성공적으로 완료되지 않는 경우에만 관찰자가 호출됩니다.
  • AFTER_COMPLETION: 관찰자는 트랜잭션 완료 단계 후에 호출됩니다.
  • BEFORE_COMPLETION: 관찰자는 트랜잭션 완료 단계 전에 호출됩니다.

다음 observer 메서드는 애플리케이션 컨텍스트에 캐시된 쿼리 결과 집합을 새로 고치지만 카테고리 트리를 업데이트하는 트랜잭션 시에만 캐시됩니다.

public void refreshCategoryTree(@Observes(during = AFTER_SUCCESS) CategoryUpdateEvent event) { ... }

다음 예와 같이 애플리케이션 범위에 설정된 Jakarta Persistence 쿼리 결과를 캐시했다고 가정합니다.

import javax.ejb.Singleton;
import javax.enterprise.inject.Produces;

@ApplicationScoped @Singleton

public class Catalog {
   @PersistenceContext EntityManager em;
   List<Product> products;
   @Produces @Catalog
   List<Product> getCatalog() {
      if (products==null) {
         products = em.createQuery("select p from Product p where p.deleted = false")
            .getResultList();
      }
      return products;
   }
}

경우에 따라 제품이 생성 또는 삭제 되는 경우도 있습니다. 이 경우 제품 카탈로그를 새로 고쳐야 합니다. 그러나 이 업데이트를 수행하기 전에 트랜잭션이 성공적으로 완료될 때까지 기다려야 합니다.

다음은 Products triggers 이벤트를 생성하고 삭제하는 빈의 예입니다.

import javax.enterprise.event.Event;

@Stateless

public class ProductManager {
   @PersistenceContext EntityManager em;
   @Inject @Any Event<Product> productEvent;
   public void delete(Product product) {
      em.delete(product);
      productEvent.select(new AnnotationLiteral<Deleted>(){}).fire(product);
   }

   public void persist(Product product) {
      em.persist(product);
      productEvent.select(new AnnotationLiteral<Created>(){}).fire(product);
   }
   ...
}

이제 Catalog 에서 트랜잭션이 완료되면 이벤트를 관찰할 수 있습니다.

import javax.ejb.Singleton;

@ApplicationScoped @Singleton
public class Catalog {
   ...
   void addProduct(@Observes(during = AFTER_SUCCESS) @Created Product product) {
      products.add(product);
   }

   void removeProduct(@Observes(during = AFTER_SUCCESS) @Deleted Product product) {
      products.remove(product);
   }

}