Reputation:
I have several asynchronous jobs that I would like to transparently handle the exception for. I'd like to put the exception handling logic in another component / class. With Seam 2, I extended an exception handler class.
For instance, I'd like to raise an event with the exception in it so that I can have several components act on it as they see fit. The most common one is one that notifies administrators.
Thanks,
Walter
Upvotes: 1
Views: 5789
Reputation: 570295
Here is an example from Part Three: New Features in EJB 3.1 that you can probably adapt:
Asynchronous Invocation of Session Beans
Asynchronous processing is a surprisingly common requirement for many enterprise applications. Some of the most obvious use cases are triggering fire-and-forget background processes, handling long-running tasks while keeping the user interface receptive or simply increasing application throughput by utilizing the benefits of parallel processing. The easiest way of implementing asynchronous processing in Java EE applications today is using Message Driven Beans. In fact, the first Message Driven Bean example in EJB 3 in Action is used to implement asynchronous order billing. More precisely, a Message Driven Bean (
OrderBillingMDB
) asynchronously bills the customer after the order is confirmed and updates the order information with the results of the billing attempt once it is completed. Figure 1 shows this scenario:Figure 1: Asynchronous order billing
While using Message Driven Beans for asynchronous processing certainly works, it also forces you to deal with messaging and JMS, even for relatively lightweight functionality. This is precisely the problem asynchronous session bean invocation is designed to solve. With this enhancement, you can do asynchronous processing simply by annotating a session bean method with the
@Asynchronous
annotation. Let's take a look at the re-factored EJB 3 in Action example for asynchronous billing using the feature:@Stateless public class OrderBillingServiceBean implements OrderBillingService { ... @Asynchronous public void billOrder(Order order) { try { // Attempt to charge the order. bill(order); // Send email notification of billing success. notifyBillingSuccess(order); order.setStatus(OrderStatus.COMPLETE); } catch (BillingException be) { // Send email notification of billing failure. notifyBillingFailure(be, order); order.setStatus(OrderStatus.BILLING_FAILED); } finally { update(order); } } ... }
Because of the
@Asynchronous
annotation, when the client invokes theOrderBillingService.billOrder
method, the call will return immediately instead of blocking until thebillOrder
method finishes executing. The EJB container will make sure the method gets executed asynchronously (probably using messaging under the hood). As you can see, the return type of the asynchronous method is void. This will probably be the case for a vast majority of asynchronous Session bean methods. However, EJB 3.1 can also support a return type ofjava.util.concurrent.Future<V>
, whereV
represents the resultant value of an asynchronous invocation. In case you are unfamiliar with it, theFuture<V>
interface allows you to do things like cancelling an asynchronous invocation, checking if an invocation is complete, check for exceptions and getting the results of an asynchronous invocation. Check out the documentation for theFuture<V>
interface here: http://java.sun.com/javase/6/docs/api/java/util/concurrent/Future.html. Let's take a quick look at an example using the Future return type. In thebillOrder
method in the previous example, we set the status of the order according to the outcome of the billing attempt and updated the order. Let's assume that the invoker updates the order themselves and wants to know what the status of the billing attempt was. We could do this by refactoring thebillOrder
method as follows:@Stateless public class OrderBillingServiceBean implements OrderBillingService { ... @Asynchronous public Future<OrderStatus> billOrder(Order order) { try { // Attempt to charge the order. bill(order); // Send email notification of billing success. notifyBillingSuccess(order); return new AsyncResult<OrderStatus>(OrderStatus.COMPLETE); } catch (BillingException be) { // Send email notification of billing failure. notifyBillingFailure(be, order); return new AsyncResult<OrderStatus> (OrderStatus.BILLING_FAILED); } } ... }
The
javax.ejb.AsyncResult<V>
object is a convenience implementation of theFuture<V>
interface. It takes the result of the asynchronous invocation as a constructor argument. There's nothing stopping you from using your own implementation ofFuture<V>
however. Asynchronous invocation supports a few other neat features like delivery guarantees and transacted send semantics. For details, check out the spec draft.
If you have a specific problem, please ask a more specific question :)
Future<V>
InterfaceUpvotes: 1