Over a million developers have joined DZone.

Spring @Async and exception handling

DZone's Guide to

Spring @Async and exception handling

· Integration Zone
Free Resource

Today’s data climate is fast-paced and it’s not slowing down. Here’s why your current integration solution is not enough. Brought to you in partnership with Liaison Technologies.


When using Spring to asynchronously execute pieces of your code you typically use the @Async annotation on your Spring @Components methods. When using the @Async annotation Spring will use AOP (Aspect Oriented Programming) to wrap your call in a Runnable. This Runnable will then be scheduled for execution on a TaskExecutor. More information about asynchronous execution and its transactional context can be found here.

Exception Handling

Spring comes with a number of pre-packaged TaskExecutors which are documented in the Spring documentation here. In practice you will likely use the ThreadPoolTaskExecutor or the SimpleAsyncTaskExecutor. When doing so you might at times wonder why a task has not been executed. This happens when an exception occurs inside the method you are trying to execute asynchronous. The aforementioned task executors do not handle the exceptions so the execution fails silently. This problem can be solved by implementing your own AsyncTaskExecutor which handles the exceptions by logging them (or in any other way you wish). Bellow you'll find an example implementation of such a AsyncTaskExecutor.

package nl.jborsje.blog.examples;

import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

public class ExceptionHandlingAsyncTaskExecutor implements AsyncTaskExecutor {
    private AsyncTaskExecutor executor;

    public ExceptionHandlingAsyncTaskExecutor(AsyncTaskExecutor executor) {
        this.executor = executor;

    public void execute(Runnable task) {

    public void execute(Runnable task, long startTimeout) {
        executor.execute(createWrappedRunnable(task), startTimeout);

    public Future
  submit(Runnable task) {
        return executor.submit(createWrappedRunnable(task));

    public  Future submit(final Callable task) {
        return executor.submit(createCallable(task));

    private  Callable createCallable(final Callable task) {
        return new Callable() {
            public T call() throws Exception {
                try {
                    return task.call();
                } catch (Exception ex) {
                    throw ex;

    private Runnable createWrappedRunnable(final Runnable task) {
        return new Runnable() {
            public void run() {
                try {
                } catch (Exception ex) {

    private void handle(Exception ex) {
        System.err.println("Error during @Async execution: " + ex);

This task executor decorates another task executor and wraps all Runnables and Callables in versions which handle the exception. In order to be able to use this task executor it has to be configured in the Spring application context as a managed bean and it has to be passed the real executor (the one that does the actual work) in its constructor. An example of such a configuration can be found bellow.

<task:annotation-driven executor="exceptionHandlingTaskExecutor" scheduler="defaultTaskScheduler" />
<bean id="exceptionHandlingTaskExecutor" class="nl.jborsje.blog.examples.ExceptionHandlingAsyncTaskExecutor">
    <constructor-arg ref="defaultTaskExecutor" />
<task:executor id="defaultTaskExecutor" pool-size="5" />
<task:scheduler id="defaultTaskScheduler" pool-size="1" />

JUnit testing

In the application context used for JUnit testing Spring beans the asynchronous execution of methods can be cumbersome. You typically want to validate the inner workings of your methods not Springs asynchronicity. To achieve this you can use the SyncTaskExecutor provided by Spring. This task executor runs the tasks it is given immediately on the thread that adds the task instead of using a thread pool and running the tasks asynchronous. This task executor is configured in the test scope application context as follows.

<task:annotation-driven executor="synchronousTaskExecutor" scheduler="defaultTaskScheduler" />
<bean id="synchronousTaskExecutor" class="org.springframework.core.task.SyncTaskExecutor" />
<task:scheduler id="defaultTaskScheduler" pool-size="1" />

Is iPaaS solving the right problems? Not knowing the fundamental difference between iPaaS and iPaaS+ could cost you down the road. Brought to you in partnership with Liaison Technologies.


Opinions expressed by DZone contributors are their own.


Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.


{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}