views:

131

answers:

1

Hi all,

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

A: 

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:

alt text

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 the OrderBillingService.billOrder method, the call will return immediately instead of blocking until the billOrder 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 of java.util.concurrent.Future<V>, where V represents the resultant value of an asynchronous invocation. In case you are unfamiliar with it, the Future<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 the Future<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 the billOrder 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 the billOrder 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 the Future<V> interface. It takes the result of the asynchronous invocation as a constructor argument. There's nothing stopping you from using your own implementation of Future<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 :)

See also

Pascal Thivent
I don't want to always do my exception handling in a try catch. I'd like to have an interceptor / handler that handles that. I guess I would write an EJB interceptor in that case?
You could also write a CDI/Weld interceptor, which is then usable for all your beans, not only EJBs. As i think about it, maybe it could even make the (not-really-beautiful)CustomExceptionHandler superfluous.
ifischer
That's what I will have to do, I didn't know if there already was an application exception handler that I could just override like in Seam.