I have an application that uses Spring Boot 2.4.3 with Spring Data Cassandra (using the default version declared in the BOM, which is 3.1.5).

When starting the app and terminating it with SIG_INT, an exception is thrown:

[SpringContextShutdownHook] WARN org.springframework.beans.factory.support.DisposableBeanAdapter - Destroy method 'close' on bean with name 'cassandraDriverConfigLoader' threw an exception
java.util.concurrent.RejectedExecutionException: event executor terminated
    at io.netty.util.concurrent.SingleThreadEventExecutor.reject(SingleThreadEventExecutor.java:926)
    at io.netty.util.concurrent.SingleThreadEventExecutor.offerTask(SingleThreadEventExecutor.java:353)
    at io.netty.util.concurrent.SingleThreadEventExecutor.addTask(SingleThreadEventExecutor.java:346)
    at io.netty.util.concurrent.SingleThreadEventExecutor.execute(SingleThreadEventExecutor.java:828)
    at io.netty.util.concurrent.SingleThreadEventExecutor.execute(SingleThreadEventExecutor.java:818)
    at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:112)
    at io.netty.util.concurrent.AbstractEventExecutor.submit(AbstractEventExecutor.java:115)
    at com.datastax.oss.driver.internal.core.util.concurrent.RunOrSchedule.on(RunOrSchedule.java:57)
    at com.datastax.oss.driver.internal.core.config.typesafe.DefaultDriverConfigLoader.close(DefaultDriverConfigLoader.java:175)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.beans.factory.support.DisposableBeanAdapter.invokeCustomDestroyMethod(DisposableBeanAdapter.java:281)
    at org.springframework.beans.factory.support.DisposableBeanAdapter.destroy(DisposableBeanAdapter.java:215)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroyBean(DefaultSingletonBeanRegistry.java:587)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingleton(DefaultSingletonBeanRegistry.java:559)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingleton(DefaultListableBeanFactory.java:1152)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingletons(DefaultSingletonBeanRegistry.java:520)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingletons(DefaultListableBeanFactory.java:1145)
    at org.springframework.context.support.AbstractApplicationContext.destroyBeans(AbstractApplicationContext.java:1105)
    at org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:1074)
    at org.springframework.context.support.AbstractApplicationContext$1.run(AbstractApplicationContext.java:990)

I've tested this in an isolated application that just launches the app and the problem persists.

If it helps, I've also analysed the problem, and found out the following: * org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration declares two beans: cassandraSession and cassandraDriverConfigLoader. * During shutdown, cassandraDriverConfigLoader bean is terminated twice (close method is called twice) * The first time it is closed is when cassandraSession bean is terminated. This bean is currently implemented in com.datastax.oss.driver.internal.core.session.DefaultSession. When theclose method is called in this class, it will internally call closePolicies method, which includes the cassandraDriverConfigLoader bean, referenced through the supplier context::getConfigLoader * The second time, it happens as expected, when cassandraDriverConfigLoader bean is terminated.

Comment From: snicoll

Thanks for the report. Paging @adutra for some insights as this exception happens in the Cassandra driver.

Comment From: spring-projects-issues

If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.

Comment From: adutra

Hi, I admit that the way some close() methods are implemented in the driver are a bit racy.

For DefaultSession, the race condition is handled in an optimistic way, see here.

For DefaultDriverConfigLoader however, no such protection exists. I created JAVA-2932 to capture this. However, we don't have plans to release a new version of the driver any time soon.

I'd suggest, if possible, to close DefaultDriverConfigLoader first, then DefaultSession. Or alternatively, don't close DefaultDriverConfigLoader explicitly, since DefaultSession will do it anyways.

Comment From: wilkinsona

Thanks, @adutra. We can't close DefaultDriverConfigLoader before DefaultSession as the bean dependencies are the other way around. I think we could, however, prevent DefaultDriverConfigLoader from being closed, and rely on DefaultSession closing it instead.

Comment From: wilkinsona

The warning is logged when running CassandraDataAutoConfigurationIntegrationTests:

2021-04-01 17:16:12.528  WARN   --- [           main] o.s.b.f.support.DisposableBeanAdapter    : Destroy method 'close' on bean with name 'cassandraDriverConfigLoader' threw an exception: java.util.concurrent.RejectedExecutionException: event executor terminated

Comment From: adutra

FYI, the fix will be delivered in driver 4.11.2, due this week.