Close

Spring - Getting completion callback using AsyncTaskExecutor submitCompletable()

[Last Updated: Dec 22, 2023]

In Spring 6.0 AsyncListenableTaskExecutor was deprecated in favor of AsyncTaskExecutor.submitCompletable(Runnable) and AsyncTaskExecutor.submitCompletable(Callable).

That means we don't need AsyncListenableTaskExecutor to receive task completion callback as we can achieve the same by using core Java CompletableFuture

Example

package com.logicbig.example;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.AsyncListenableTaskExecutor;
import org.springframework.core.task.SimpleAsyncTaskExecutor;

import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;

public class AsyncTaskExecutorCompletableFutureExample {

    public static void main(String[] args) throws Exception {
        ApplicationContext context =
                new AnnotationConfigApplicationContext(MyConfig.class);
        MyBean bean = context.getBean(MyBean.class);
        bean.runTasks();
    }

    @Configuration
    public static class MyConfig {

        @Bean
        MyBean myBean() {
            return new MyBean();
        }

        @Bean
        AsyncListenableTaskExecutor taskExecutor() {
            SimpleAsyncTaskExecutor t = new SimpleAsyncTaskExecutor();
            t.setConcurrencyLimit(100);
            return t;
        }
    }

    private static class MyBean {
        @Autowired
        private AsyncListenableTaskExecutor executor;

        public void runTasks() throws Exception {

            for (int i = 0; i < 10; i++) {
                CompletableFuture<String> completableFuture =
                        executor.submitCompletable(getTask(i));
                completableFuture.thenAccept(task -> System.out.println("Completed: " + task));
            }
        }

        private Callable<String> getTask(int i) {
            return () -> {
                System.out.printf("running task %d. Thread: %s%n",
                        i,
                        Thread.currentThread().getName());
                return String.format("Task finished %d", i);
            };
        }
    }
}

Output

running task 0. Thread: SimpleAsyncTaskExecutor-1
running task 1. Thread: SimpleAsyncTaskExecutor-2
running task 2. Thread: SimpleAsyncTaskExecutor-3
running task 3. Thread: SimpleAsyncTaskExecutor-4
running task 5. Thread: SimpleAsyncTaskExecutor-6
Completed: Task finished 5
Completed: Task finished 0
Completed: Task finished 1
running task 8. Thread: SimpleAsyncTaskExecutor-9
running task 4. Thread: SimpleAsyncTaskExecutor-5
Completed: Task finished 8
running task 7. Thread: SimpleAsyncTaskExecutor-8
running task 9. Thread: SimpleAsyncTaskExecutor-10
Completed: Task finished 9
running task 6. Thread: SimpleAsyncTaskExecutor-7
Completed: Task finished 3
Completed: Task finished 2
Completed: Task finished 6
Completed: Task finished 7
Completed: Task finished 4

Example Project

Dependencies and Technologies Used:

  • spring-context 6.1.2 (Spring Context)
     Version Compatibility: 6.0.0 - 6.1.2Version List
    ×

    Version compatibilities of spring-context with this example:

      Compatible Java Version: 17+
    • 6.0.0
    • 6.0.1
    • 6.0.2
    • 6.0.3
    • 6.0.4
    • 6.0.5
    • 6.0.6
    • 6.0.7
    • 6.0.8
    • 6.0.9
    • 6.0.10
    • 6.0.11
    • 6.0.12
    • 6.0.13
    • 6.0.14
    • 6.0.15
    • 6.1.0
    • 6.1.1
    • 6.1.2

    Versions in green have been tested.

  • JDK 17
  • Maven 3.8.1

AsyncTaskExecutor#SubmitCompletable Example Select All Download
  • spring-async-task-executor-completable-future-example
    • src
      • main
        • java
          • com
            • logicbig
              • example
                • AsyncTaskExecutorCompletableFutureExample.java

    See Also