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

  1. 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.