Affects: 6.0.4
Problem
When an ApplicationContext with a org.springframework.core.task.support.ExecutorServiceAdapter
bean present is closed, the shutdown()
method of ExecutorServiceAdapter
gets called which throws an IllegalStateException
leading to a warning:
Jan. 27, 2023 1:41:44 PM org.springframework.beans.factory.support.DisposableBeanAdapter invokeCustomDestroyMethod
WARNUNG: Custom destroy method 'shutdown' on bean with name 'executorService' threw an exception: java.lang.IllegalStateException: Manual shutdown not supported - ExecutorServiceAdapter is dependent on an external lifecycle
Steps to reproduce
-
Configure an ApplicationContext with a
ExecutorServiceAdapter
bean ```java @Configuration public class Config {@Bean public TaskExecutor taskExecutor() { return new ThreadPoolTaskExecutor(); }
@Bean public ExecutorService executorService(TaskExecutor taskExecutor) { return new ExecutorServiceAdapter(taskExecutor); } } ``` 2. Start and stop the ApplicationContext:
public class Main {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = new AnnotationConfigApplicationContext(Config.class);
applicationContext.getBean("executorService", ExecutorService.class);
applicationContext.close();
}
}
Or have a look at a sample project that reproduces the error.
Comment From: jhoeller
I suppose this is caused by the introduction of a default AutoCloseable.close()
implementation in the ExecutorService
interface in JDK 19? Are you experiencing this on JDK 19 only? In this case, we can probably override close()
in a custom fashion to avoid that effect.
Comment From: sbrannen
This actually happens on any JDK.
With the ExecutorServiceAdapter
configured via a @Bean
factory method, the destroyMethod
attribute defaults to (inferred)
, and DisposableBeanAdapter#inferDestroyMethodsIfNecessary()
registers the shutdown
method as the destroy-method.
Comment From: jhoeller
Ah yes, I should have noticed the "shutdown" name in the exception message. In any case, there is a difference in the bean lifecycle for such beans on JDK 19+ now since we'll prefer the new close
method over shutdown
, waiting for tasks to terminate according to the default close
implementation. Makes no difference for this adapter case but generally worth keeping in mind.