0

I'm trying to copy Spring context to Runnable/Callable tasks for a special case. I want other threads to run as they run before.

I've read this How to enable request scope in async task executor

and implemented a custom ThreadPoolTaskExecutor + decorator.

@Configuration
public class ContextCopyConfig {

    private Integer connectionsLimit=10;

    @Bean(name = "contextExecutor")
    public Executor contextExecutor() {
        ThreadPoolTaskExecutor poolExecutor = new ThreadPoolTaskExecutor();
        poolExecutor.setTaskDecorator(new ContextCopyingDecorator());
        poolExecutor.setMaxPoolSize(connectionsLimit);
        poolExecutor.setCorePoolSize(connectionsLimit);

        poolExecutor.initialize();
        return poolExecutor;
    }

}

I was planning to use this executor as follows:

@Autowired
@Qualifier(value = "contextExecutor")
private Executor contextExecutor;

public void parallelHere() throws IOException, InterruptedException, ExecutionException {
    Collection<Callable<Pair<String, OutputStream>>> tasks = new ArrayList<>(); //some tasks

    //ExecutorService executor = Executors.newFixedThreadPool(connectionsLimit); 

    List<Future<Pair<String, OutputStream>>> results = ((ThreadPoolTaskExecutor) contextExecutor).getThreadPoolExecutor().invokeAll(tasks);
    ((ThreadPoolTaskExecutor) contextExecutor).getThreadPoolExecutor().shutdown(); //always reclaim resources
}

However, contextExecutor is always invoked (in any thread!). How can I fix it?

Ermintar
  • 1,322
  • 3
  • 22
  • 39

1 Answers1

1

This post:

How to create additional TaskExecutor beside TaskExecutionAutoConfiguration?

describes the issue. Springboot creates a default Executor only if user did not create a custom one. In SpringBoot 2+ you have to use

@AutoConfigureAfter(TaskExecutionAutoConfiguration.class)

on your custom configuration.

In previous Spring versions however, no TaskExecutionAutoConfiguration exists and Executor is created by a factory. Using lines below, you can create the exect copy of default executor, created by Spring.

@Primary
@Bean
//see package org.springframework.aop.interceptor.AsyncExecutionInterceptor
public Executor getDefaultExecutor(){
    //     Executor defaultExecutor = super.getDefaultExecutor(beanFactory);
    //     return (defaultExecutor != null ? defaultExecutor : new SimpleAsyncTaskExecutor());
    return new SimpleAsyncTaskExecutor();
}
Ermintar
  • 1,322
  • 3
  • 22
  • 39