Weld SiteCommunity Documentation

Chapter 10. public void afterPersonalBlogUpdate(@Observes @Updated @Personal @Blog Document document) { … }

10.1. Transactional observers
10.2. Enhanced version of javax.enterprise.event.Event

It would not be notified, as @Personal is not a qualifier of the event being fired. Or to put it more formally, @Updated and @Personal do not form a subset of @Blog and @Updated.

Transactional observers receive their event notifications during the before or after completion phase of the transaction in which the event was raised. For example, the following observer method needs to refresh a query result set that is cached in the application context, but only when transactions that update the Category tree succeed:

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

There are five kinds of transactional observers:

Transactional observers are very important in a stateful object model because state is often held for longer than a single atomic transaction.

Imagine that we have cached a JPA query result set in the application scope:

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;
   }
}

From time to time, a Product is created or deleted. When this occurs, we need to refresh the Product catalog. But we should wait until after the transaction completes successfully before performing this refresh!

The bean that creates and deletes `Product`s could raise events, for example:

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);
   }
   ...
}

And now Catalog can observe the events after successful completion of the transaction:

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);
   }
}

Weld API offers slight advantage when dealing with events - org.jboss.weld.events.WeldEvent, an augmented version of javax.enterprise.event.Event.

Currently there is only one additional method, select(Type type, Annotation... qualifiers). This method allows to perform well-known selection with java.lang.reflect.Type as parameter which means things can get pretty generic. While there are no limitations to what you can select, there are limitation to the WeldEvent instance you perform selection on. In order to preserve type-safety, you have to invoke this method on WeldInstance<Object>. Using any other parameter will result in IllegalStateException. Usage looks just as you would except:

@Inject

WeldEvent<Object> event;
public void selectAndFireEventForType(Type type) {
  event.select(type).fire(new Payload());
}