Issue with a Spring @Async method not catching/rethrowing an exception

Your logs show

2014-06-20 18:46:29,249 [ThreadPoolTaskExecutor-1] ERROR com.bignibou.service.preference.PreferenceServiceImpl - MessagingException | MailSendException

which is logged by

log.error("MessagingException | MailSendException", e);

the Exception that is then thrown

throw new MailerException("MessagingException | MailSendException");//NOT CALLED

is caught by the Thread executed by the underlying ThreadPoolTaskExecutor. This code is run asynchronously so the exception is thrown in a different thread than the thread that invokes the method.

someCode();
yourProxy.sendPasswordResetInfo(someValue()); // exception thrown in other thread
moreCode();

If you make your method return a Future as shown here you'll be able to invoke get() on it and that will rethrow any exception that was thrown inside the @Async method, wrapped in an ExecutionException.


By following this link http://www.baeldung.com/spring-async, you should create:

  1. CustomAsyncExceptionHandler that implements AsyncUncaughtExceptionHandler

    @Slf4j
    public class CustomAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
      @Override
      public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {
        log.error("**********************************************");
        log.error("Exception message - " + throwable.getMessage());
        log.error("Method name - " + method.getName());
        for (Object param : obj) {
            log.error("Parameter value - " + param);
        }
        log.error("**********************************************");
      }
    }
    
  2. SpringAsyncConfig that implements AsyncConfigurer

    @Configuration
    @EnableAsync
    public class SpringAsyncConfig implements AsyncConfigurer {
    
      @Override
      public Executor getAsyncExecutor() {
        return new ThreadPoolTaskExecutor();
      }
    
      @Override
      public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new CustomAsyncExceptionHandler();
      }
    }