Nov 10, 2018

Asynchronous Invocations in EJB 3.1 +

Session beans can implement asynchronous methods, business methods where control is returned to the client by the enterprise bean container before the method is invoked on the session bean instance. Clients may then use the Java SE concurrency API to retrieve the result, cancel the invocation, and check for exceptions. Asynchronous methods are typically used for long-running operations, for processor-intensive tasks, for background tasks, to increase application throughput, or to improve application response time if the method invocation result isn’t required immediately.

When a session bean client invokes a typical non-asynchronous business method, control is not returned to the client until the method has completed. Clients calling asynchronous methods, however, immediately have control returned to them by the enterprise bean container. This allows the client to perform other tasks while the method invocation completes. If the method returns a result, the result is an implementation of the java.util.concurrent.Future<V> interface, where “V” is the result value type. The Future<V> interface defines methods the client may use to check whether the computation is completed, wait for the invocation to complete, retrieve the final result, and cancel the invocation.

An asynchronous method is applied by the Asynchronous annotation to a method or to a class/interface.

Example:
@Local
public interface CLocal {
    public void flushBye();
}
@Remote
@Asynchronous
public interface CRemote {
    public void flushBye();
}
It is asynchronous If invoked through the remote interface, synchronous if from local interface.

The return type of an asynchronous method must be void or Future<V>, being V the result value type. If void is used then the method cannot declare any application exception.

The container provides the class AsyncResult<V>, consisting of an implementation of the interface Future<V> which takes the result value as constructor's parameter.
@Asynchronous
public Future doLongProcess() {
    String i88ca = longProcess();
    return new AsyncResult(i88ca);
}
The SessionContext interface has the method wasCancelCalled, which returns true if the method Future.cancel was invoked by the client, setting the parameter mayInterruptIfRunning as true.

@Resource
SessionContext ctx;

@Asynchronous
public Future doLongProcess() {
    String i88ca = doLongProcess();
    if (!ctx.wasCancelCalled()){
        i88ca += doAnotherLongProcess();
    }
    return new AsyncResult(i88ca);
}