Close

Spring Framework - ListenableFutureCallback Examples

Spring Framework 

AsyncListenableTaskExecutor#submitListenable returns ListenableFuture which can add ListenableFutureCallback instance as shown in this 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 org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.ListenableFutureCallback;

import java.util.concurrent.Callable;

public class AsyncListableTaskExecutorExample {

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;
}

@Bean
ListenableFutureCallback<String> taskCallback () {
return new MyListenableFutureCallback();
}
}

private static class MyBean {
@Autowired
private AsyncListenableTaskExecutor executor;
@Autowired
private ListenableFutureCallback threadListenableCallback;


public void runTasks () throws Exception {

for (int i = 0; i < 10; i++) {
ListenableFuture<String> f =
executor.submitListenable(getTask(i));
f.addCallback(threadListenableCallback);
}
}

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);
};
}
}

private static class MyListenableFutureCallback
implements ListenableFutureCallback<String> {
@Override
public void onFailure (Throwable ex) {
System.out.println("faliure message: " + ex.getMessage());
ex.printStackTrace();
}

@Override
public void onSuccess (String result) {
System.out.println("success object: " + result);
}
}
}

Output

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




In Spring 6.0 AsyncListenableTaskExecutor has been deprecated in favor of AsyncTaskExecutor's method which return CompletableFuture.

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
Original Post




See Also