You can use the sample code within this topic to develop client code that calls EJB asynchronous methods.
public interface AcmeRemoteInterface { void fireAndForgetMethod (); Future<Integer> methodWithResults() throws AcmeException1, AcmeException2; }
@Stateless @Remote(AcmeRemoteInterface.class) @Asynchronous public class AcmeAsyncBean { public void fireAndForgetMethod () { // do non-critical work } public Integer methodWithResults() { Integer result; // do work, and then return results return result; } }
@EJB AcmeRemoteInterface myAsyncBean; try { myAsyncBean.fireAndForgetMethod(); } catch (EJBException ejbex) { // Asynchronous method never dispatched, handle system error }
@EJB AcmeRemoteInterface myAsyncBean; Future<Integer>myFutureResult = null; Integer myResult = null; try { myFutureResult = myAsyncBean.methodWithResults(); } catch (EJBException ejbex) { // Asynchronous method call was not dispatched; handle exception. } // The asynchronous method call will be dispatched on another thread. Do other // work on this thread, and then wait for results. // ... try { myResult = myFutureResult.get(); } catch (InterruptedException iex) { // Asynchronous method execution interrupted, handle exception } catch (ExecutionException eex) { // Exception during asynchronous method execution, handle exception }
myResult = myFutureResult.get(5, TimeUnit.SECONDS);
while (!myFutureResult.isDone()) { // Execute other work while waiting for the asynchronous method to complete. } // This call is guaranteed not to block because isDone returned true. myResult = myFutureResult.get();
@EJB AcmeRemoteInterface myAsyncBean; Future<Integer>>myFutureResult = null; Integer myResult = null; try { myFutureResult = myAsyncBean.methodWithResults(); } catch (EJBException ejbx) { // Asynchronous method never dispatched, handle exception } // Method is eventually dispatched. Wait for results. try { myResult = myFutureResult.get(); } catch (ExecutionException ex) { // Determine which application exception that occurred during the // asynchronous method call. Throwable theCause = ex.getCause(); if (theCause instanceof AcmeException1) { // Handle AcmeException1 } else if (theCause instanceof AcmeException2) { // Handle AcmeException2 } else { // Handle other causes. } } catch ( ... ) { // Handle other exception. }
@EJB AcmeRemoteInterface myAsyncBean; Future<Integer>>myFutureResult = null; Integer myResult = null; try { myFutureResult = myAsyncBean.methodWithResults(); } catch (EJBException ejbx) { // Asynchronous method was not dispatched; handle exception. } // Method will eventually be dispatched so block now and wait for results try { myResult = myFutureResult.get(); } catch (ExecutionException ex) { // Find the exception class that occurred during the asynchronous method Throwable theCause = ex.getCause(); if (theCause instanceof EJBException) { // Handle the EJBException that might be wrapping a system exception // which occurred during the asynchronous method execution. Throwable theRootCause = theCause.getCause(); if (theRootCause != null) { // Handle the system exception } } else ... // handle other causes } catch (...) { // handle other exceptions }
@EJB AcmeRemoteInterface myAsyncBean; Future<Integer> myFutureResult = myFutureResult.methodWithResults(); Integer myResult; if (myFutureResult.cancel(true)) { // Asynchronous method was not dispatched. } else { // Asynchronous method already started executing. The bean can still check // whether an attempt was made to cancel the call. } if (myFutureResult.isCancelled()) { // Asynchronous method call did not start executing because the cancel // method returned true in a previous line of the example. } try { myResult = myFutureResult.get(); } catch (CancellationException ex) { // Handle the exception that occurs because the cancel method returned true // in a previous line of the example. }
@Resource SessionContext myContext; public Future<Integer> methodWithResults() { for (int i = 0; i < 3; i++) { // Do one piece of long-running work. // Before continuing, check whether the client attempted to cancel this work. if (myContext.wasCancelCalled()) { throw new AcmeCancelCalledException(); } } // ... }
In some cases, a method must pass back multiple pieces of data.
One way to accomplish this task is by using pass-by-reference semantics. In this approach, an object is passed into the method as a parameter, updated by the method, and then the updated value is available to the client. This approach does work for asynchronous methods, but it is not the optimal pattern.
To return multiple pieces of data, create a wrapper inside the Future object that is returned by the method. In this approach, a wrapper object is defined that contains instance variables which hold the different pieces of data that must be returned. The asynchronous method sets these pieces of data into the wrapper object and returns it, and the client code then retrieves this data from the Future object.
Embedding multiple pieces of data inside the wrapper object is a local or remote, transparent pattern, that identifies exactly when the results are available. In contrast, the traditional pass-by-reference technique does not give the client an easy way to determine when the results are available. The passed in object is not updated until the asynchronous method runs, and the client cannot determine when that has occurred, other than by interrogating the Future object using the Future.isDone() or Future.get() methods.
// This is the result object that is returned from the asynchronous method. // This object is wrappered in a Future object, and it contains the two pieces of data // that must be returned from the method. class ResultObject { public Boolean myResult; pubilc String myInfo; }
// This is the asynchronous method code that gets the results and returns them. @Asynchronous public Future<ResultObject> asyncMethod1(Object someInputData) { boolean result = doSomeStuff(); String info = doSomeMoreStuff(); ResultObject theResult = new ResultObject(); theResult.myResult = result; theResult.myInfo = info; return new javax.ejb.AsyncResult<ResultObject>(theResult); }
// This is the client code that obtains the ResultObject, and then extracts the needed data from it. Future<ResultObject> myFutureResult = myBeanRef.asyncMethod1(someInputData); ResultObject theResult = myFutureResult.get(); boolean didItWork = theResult.myResult; String explanation = theResult.myInfo;
In this information ...Related concepts
| IBM Redbooks, demos, education, and more(Index) Use IBM Suggests to retrieve related content from ibm.com and beyond, identified for your convenience. This feature requires Internet access. Most of the following links will take you to information that is not part of the formal product documentation and is provided "as is." Some of these links go to non-IBM Web sites and are provided for your convenience only and do not in any manner serve as an endorsement by IBM of those Web sites, the material thereon, or the owner thereof. |