Since the introduction of EJB 3.1 we can use the @Asynchronous annotation. It provides a simple way to create a new asynchronous process in your application.
If a method with the @Asynchronous is invoked it will spawn a new thread and return immediately. The invocation can return either a void or a [Future
To find out more about how to use @Asynchronous and Future, read this page from TomEE.
The problem I’ve found with this annotation is how it handles RuntimeException. If you have a void as return value, and inside the asynchronous method a RuntimeException occurs, it’ll be completely swallowed. Nothing will be send to your logs. This is something I couldn’t find in any documentation.
If you create a new Thread yourself (see example below) it will print the RuntimeException:
When executed you’ll end up with the exception nicely printed in the console. But this isn’t the case for @Asynchronous. For example if you do:
This exception is swallowed, never to be seen again. Because this wasn’t what I expected it took me much longer then needed to find the actual bug!
To fix this problem you can instead return a Future and call get(). When calling get() on a Future, and the asynchronous method ends with an exception, it’ll immediately throw an ExecutionException which wraps around the asynchronous exception (call getCause() to get it).
But calling get() basically makes the call synchronous again instead of the fire-and-forget I wanted to have. So instead I’ve now ended up with a big try/catch block around the entire @Asynchronous method. It feels a bit wrong… did I miss something? Is there a better method to log the RuntimeException from @Asynchronous methods?