CDI Events – Synchronous x Asynchronous

Context Dependency Injection or CDI (JSR-220 / JSR-330) is one of the greatest features of Java EE 6.  It brings simplicity to a lot of areas where previous version of Java EE required tons of Interfaces, XML’s and a lot of boilerplate code to create simple things.

This post is going to show some simple examples on how to use Java EE 6 and CDI Events with synchronous and asynchronous patterns, which is also part of the new specifications.

First, let’s define what synchronous and asynchronous means in this context:

Synchronous – Execution or processing that happens on the same thread and need immediate response or process completion to continue. It also means that a call to a synchronous method will block (wait) the caller until it’s completion. Example: A traditional HTTP Request.

Asynchronous – Execution or processing that doesn’t need immediate or any response and will be processed on a different thread than the caller’s thread. This means that an asynchronous caller doesn’t need to be waiting for the process to complete and may receive a callback when the work is done. Example: Sending a JMS message, Performing an AJAX call on a web page.

Thread Pools

Thread Pools are one of the most efficient patterns when dealing with Threads. Conceptually it works as a pool of workers and a queue of tasks which get’s executed by different threads. When those threads finishes processing the task, it will automatically get the next one on the queue to process until the queue is empty. The thread lifecycle is also managed by the pool, so a well managed pool can save a lot of resources keeping the number of threads to a good level maintaining the balance between number of threads and tasks on the queue.

Application Servers have to deal with several (thousands, millions..) of requests and different services like JDBC, JMS, EJB and JCA, each of theses tasks consumes threads to complete their work. So, internally most application servers create thread pools to isolate the resource consumption of these tasks and make a better usage of hardware threads according to the applications needs.

Synchronous Events

The default strategy for CDI events is synchronous, which is very simple to implement.

// imports omitted for brevity
@Named
public ShoppingCart {

  @Inject
  Event<String> eventService;

  public void checkout(OrderEvent event) {
      eventService.fire(event);
  }
}

And to receive/observe the event:

// imports omitted for brevity
@Named
public PaymentHandler {

 public void onNewOrder(@Observers OrderEvent event) {

     Log.info("Event captured - " + event)
  }
}

It’s also possible to use Qualifiers and perform kind of “selector” (for reference check this) and filter the events based on the qualifiers.

When you deploy an application with these beans and consume them from a JSF page or a Servlet, the request will be processed consuming a Thread from the HTTP Thread Pool that will stay in use until the response is committed.  Let’s assume you have multiple @Observers for the same event. In this case, all the work done by the @Observers will occur on the same Thread as the request, which is in this case the HTTP request.

Depending on the scenario, this behavior is acceptable, but if your @Observers are performing long-running tasks and you have users waiting for their request to complete on a web application, it may not be the case.

This can be easily addressed with a real Asynchronous processing for events and observers.

Asynchronous Events

Asynchronous events can be implemented using CDI and EJB with the help of @Asynchronous annotation.

First, let’s write a Stateless EJB that will be responsible for dispatching the events:

// imports omitted for brevity
@Named("EventDisptacherBean")
@Stateless
public class EventDispatcherBean {

     private static final Logger logger = Logger.getLogger(EventDispatcherBean.class.getCanonicalName());

    @Inject
    Event<OrderEvent> eventManager;

    @Asynchronous
    public void publish(OrderEvent event) {
        logger.log(Level.FINEST, "{0} Sending event from EJB", Thread.currentThread().getName());
        eventManager.fire(event);
    }
}

Please note the usage of the @Asynchronous annotation on the publish method, this will decouple the Thread from the HTTP request and pass the processing context to the EJB Thread pool and since the return is set as void, this will be processed as a fire-and-forget call, where no return is expected. (off-topic: I do appreciate the reference to fire-n-forget missiles)

// imports omitted for brevity
@Stateless
public class DeliveryHandler implements Serializable {

    private static final Logger logger = Logger.getLogger(DeliveryHandler.class.getCanonicalName());

    @EJB
    OrderBean orderBean;

    @Override
    @Asynchronous
    public void onNewOrder(@Observes OrderEvent event) {

        logger.log(Level.FINEST, "{0} Event being processed by DeliveryHandler", Thread.currentThread().getName());

        try {
            logger.log(Level.INFO, "Order #{0} has been paid amount of {1}. Order ready to delivery!", new Object[]{event.getOrderID(), event.getAmount()});

            orderBean.setOrderStatus(event.getOrderID(), OrderBean.Status.READY_TO_SHIP);

        } catch (Exception jex) {
            logger.log(Level.SEVERE, null, jex);
        }
    }
}

Then, there is the event observer and as you can see it also uses the @Asynchronous annotation, which will decouple the event processing from the event publisher as this bean is also an EJB, so it will only consume Threads from the EJB Thread pool.

With this modification, we should be able to get a higher throughput on the web application since we’re not sharing threads to process HTTP requests and CDI events, each of them with it’s own Thread Pool.

For more details, check the complete implementation of this application available as part of the Java EE 6 Tutorial case study – Duke’s Forest.

5 thoughts on “CDI Events – Synchronous x Asynchronous

  1. They indeed don’t need to be void, but that’s what make them “fire-n-forget”, since you don’t really care about the return. Not sure about missile link. :)

    Thanks!

  2. I do not understand, why the publish Method (async use case) needs to be annotated as @Asynchronous. It seems that it is asynchronous too, if I do not annotate it: If I make the event itself to take e.g. 5s and my firing function (your publish Method) is called from a HTTP-Request, I can see in the browser (which sends the request), that it receives the response immediately; so this seems to be a proof, that the publish Method and the event handler function is already decoupled.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s