Miles to go …

May 18, 2010

TOTD #137: Asynchronous EJB, a light-weight JMS solution – Feature-rich Java EE 6

Filed under: General — arungupta @ 11:00 pm

One of the new features introduced in Enterprise Java Beans 3.1 (JSR 318)  is asynchronous invocation of a business method. This allows the control to return to the client before the container dispatches the instance to a bean. The asynchronous operations can return a "Future<V>" that allow the client to retrieve a result value, check for exceptions, or attempt to cancel any in-progress invocations.

The "@Asynchronous" annotation is used to mark a specific (method-level) or all (class-level) methods of the bean as asynchronous. Here is an example of a stateless session bean that is tagged as asynchronous at the class-level:

@Stateless
@Asynchronous
public class SimpleAsyncEJB {
public Future<Integer> addNumbers(int n1, int n2) {
Integer result;
result = n1 + n2;
try {
// simulate JPA queries + reading file system
Thread.currentThread().sleep(2000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
return new AsyncResult(result);
}
}

The method signature returns "Future<Integer>" and the return type is "AsyncResult(Integer)". The "AsyncResult" is a new class introduced in EJB 3.1 that wraps the result of an asynchronous method as a Future object. Under the covers, the value is retrieved and sent to the client. Adding any new methods to this class will automatically make them asynchronous as well.

The 2 second sleep simulates server side processing of the response which may involve querying the database or reading some information from the filesystem.

This EJB can be easily injected in a Servlet using the normal way:

@EJB SimpleAsyncEJB ejb;

This business method can be invoked in the "doGet" method of a Servlet as:

PrintWriter out = response.getWriter();
try {
Future<Integer> future = ejb.addNumbers(10, 20);
print(out, "Client is working ...");
Thread.currentThread().sleep(1000);
if (!future.isDone()) {
print(out, "Response not ready yet ...");
}
print(out, "Client is working again ...");
Thread.currentThread().sleep(1000);
if (!future.isDone()) {
print(out, "Response not ready yet ...");
}
print(out, "Client is still working ...");
Thread.currentThread().sleep(1000);
if (!future.isDone()) {
print(out, "Response not ready yet ...");
} else {
print(out, "Response is now ready");
}
Integer result = future.get();
print(out, "The result is: " + result);
} catch (InterruptedException ex) {
ex.printStackTrace();
} catch (ExecutionException ex) {
ex.printStackTrace();
} finally {
out.close();
}

The control is returned to the client right after the the EJB business method is invoked and does not wait for the business method execution to finish. The methods on "Future" API are used to query if the result is available. The "Thread.sleep()" for 1 second simulate that client can continue working and possibly check for results at a regular interval. The "print" is a convenience method that prints the string to "response.getWriter" and flushes the output so that it can be instantly displayed instead of getting buffered. Invoking this "doGet" shows the following output:

1274142978365: Client is working ...
1274142979365: Response not ready yet ...
1274142979365: Client is working again ...
1274142980366: Response not ready yet ...
1274142980366: Client is still working ...
1274142981366: Response is now ready
1274142981366: The result is: 30

The client transaction context does not and security context do propagate from the client to the asynchronous business method.

Up until now, any kind of asynchrony in the EJB required to use the Message Driven Beans which in turn required some JMS setup. Introduction of this feature allows you to easily incorporate asynchrony in your EJB applications.

Try this and other Java EE 6 features in GlassFish Server Open Source Edition 3 or Oracle GlassFish Server today!

The complete source code used in this blog can be downloaded here.

Technorati: totd javaee ejb asynchronous glassfish v3

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • DZone
  • StumbleUpon
  • Technorati
  • Twitter
  • Slashdot
Related posts:
  1. TOTD #145: CDI Events – a light-weight producer/consumer in Java EE 6
  2. TOTD #139: Asynchronous Request Processing using Servlets 3.0 and Java EE 6
  3. QA#1 – Java EE 6: Standards compliance, Vendor independence, Light-weight deployment – by Adam Bien
  4. TOTD #102: Java EE 6 (Servlet 3.0 and EJB 3.1) wizards in Eclipse
  5. TOTD #134: Interceptors 1.1 in Java EE 6 – What and How ?

1 Comment »

  1. Thread.currentThread().sleep(2000);
    should be written as
    Thread.sleep(2000);
    because sleep is a static method

    Comment by bob — December 16, 2010 @ 2:34 am

RSS feed for comments on this post. TrackBack URL

Leave a comment

The views expressed on this blog are my own and do not necessarily reflect the views of Oracle.
Powered by WordPress