Asynchronous Execution

EJBs provide support for asynchronous execution of business logic wherein the calling thread (invoking the EJB business method) is released and the actual processing takes place in a background thread which is managed by the EJB container itself.

The EJB specification provided us the following options

  • Asynchronous Beans
  • Message Driven Beans

@Asynchronous

Using MDBs (along with a full fledged JMS infrastructure setup) is not something which you would want to commit to, if all you need is a few methods to be invoked asynchronously. In case you do not need strict decoupling b/w sender and receiver and the rich features of enterprise messaging offered by JMS, an easier way of adopting the asynchronous processing paradigm is via the @Asynchronous annotation.

package ejbap.async;

import javax.ejb.Asynchronous;
import javax.ejb.Stateless;

@Stateless
@Asynchronous
public class EmailService {

    public void sendMail() {

        System.out.println("Sending email......");
        try {
            //for sample purposes ONLY
            Thread.sleep(5000);
        } catch (InterruptedException ex) {
            throw new RuntimeException(ex);
        }
    }

}

In the above example, the annotated method returns void. One also can return a parameterized java.util.concurrent.Future object i.e. Future<T>. Think of it like a tracking ID for your order - you can invoke methods on it to introspect the status of the asynchronous invocation or even cancel your it !

package ejbap.async;

import java.util.UUID;
import java.util.concurrent.Future;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.AsyncResult;
import javax.ejb.Asynchronous;
import javax.ejb.Stateless;

@Stateless
public class DataService {

    @Asynchronous
    public Future<String> fetch() {
        System.out.println("Invocation thread -- " + Thread.currentThread().getName());
        return new AsyncResult<>(longRunningMethod());
    }

    private String longRunningMethod() {
        System.out.println("Async execution thread -- " 
                + Thread.currentThread().getName());

        try {
            //for sample purposes ONLY
            Thread.sleep(5000);

        } catch (InterruptedException ex) {
            throw new RuntimeException(ex);
        }

        return UUID.randomUUID().toString();
    }
}

@Asynchronous is applicable on individual methods as well as classes. In case it is used on a class, all the methods of that EJB would execute asynchronously

@ActivationConfigProperty

This annotation is used to declaratively configure a Message driven bean. It accepts name value pairs where the name represents an attribute

Message Driven Beans are powered by the @MessageDriven annotation. Please refer to the EJB Core chapter for a detailed discussion on this.

package ejbap.async;

import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;

@MessageDriven(activationConfig = {
    @ActivationConfigProperty(propertyName = "destinationLookup",
            propertyValue = "java:comp/env/orderQueue"),
    @ActivationConfigProperty(propertyName = "destinationType",
            propertyValue = "javax.jms.Queue")
})
public class MDBWithActivationConfig implements MessageListener{

    @Override
    public void onMessage(Message msg) {
        try {
            emailOrderDetails(msg);
        } catch (JMSException ex) {
            throw new RuntimeException(ex);
        }
    }

    private void emailOrderDetails(Message msg) throws JMSException{
        //logic to send order details...
    }

}

As you noticed, the destinationType and destinationLookup attributes were used in the above example. There are a set of standard attributes which are applicable for Message driven beans which listen to JMS destinations (topics and queues)

  • messageSelector: specifies selectors to be used for filtration
  • connectionFactoryLookup: connection factory of the JMS provider
  • clientId: used while connecting to JMS provider
  • subscriptionName: name of the durable subscription in case the MDB is configured to listen to a Topic
  • subscriptionDurability: type of subscription, either Durable or NonDurable
  • acknowledgeMode: acknowledgement mode to be used, either Auto_acknowledge or Dups_ok_acknowledge

Looking ahead ...

We'll dive into the eager initilization feature provided by Singleton EJBs.

results matching ""

    No results matching ""