Merge pull request #41695 from facewise

* pr/41695:
  Make IntegrationTaskSchedulerConfiguration virtual threads aware

Closes gh-41695
This commit is contained in:
Moritz Halbritter 2024-08-06 09:33:32 +02:00
commit abe3ee6831
2 changed files with 38 additions and 3 deletions

View File

@ -32,6 +32,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
import org.springframework.boot.autoconfigure.condition.ConditionalOnThreading;
import org.springframework.boot.autoconfigure.condition.SearchStrategy;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration;
@ -39,9 +40,11 @@ import org.springframework.boot.autoconfigure.jmx.JmxProperties;
import org.springframework.boot.autoconfigure.rsocket.RSocketMessagingAutoConfiguration;
import org.springframework.boot.autoconfigure.sql.init.OnDatabaseInitializationCondition;
import org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration;
import org.springframework.boot.autoconfigure.thread.Threading;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.context.properties.PropertyMapper;
import org.springframework.boot.context.properties.source.MutuallyExclusiveConfigurationPropertiesException;
import org.springframework.boot.task.SimpleAsyncTaskSchedulerBuilder;
import org.springframework.boot.task.ThreadPoolTaskSchedulerBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
@ -65,6 +68,7 @@ import org.springframework.messaging.rsocket.RSocketRequester;
import org.springframework.messaging.rsocket.RSocketStrategies;
import org.springframework.messaging.rsocket.annotation.support.RSocketMessageHandler;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.concurrent.SimpleAsyncTaskScheduler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.scheduling.support.PeriodicTrigger;
@ -79,6 +83,7 @@ import org.springframework.util.StringUtils;
* @author Stephane Nicoll
* @author Vedran Pavic
* @author Madhura Bhave
* @author Yong-Hyun Kim
* @since 1.1.0
*/
@AutoConfiguration(after = { DataSourceAutoConfiguration.class, JmxAutoConfiguration.class,
@ -165,19 +170,31 @@ public class IntegrationAutoConfiguration {
}
/**
* Expose a standard {@link ThreadPoolTaskScheduler} if the user has not enabled task
* scheduling explicitly.
* Expose a standard {@link org.springframework.scheduling.TaskScheduler
* TaskScheduler} if the user has not enabled task scheduling explicitly. A
* {@link SimpleAsyncTaskScheduler} is exposed if the user enables virtual threads via
* {@code spring.threads.virtual.enabled=true}, otherwise
* {@link ThreadPoolTaskScheduler}.
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnBean(ThreadPoolTaskSchedulerBuilder.class)
@ConditionalOnMissingBean(name = IntegrationContextUtils.TASK_SCHEDULER_BEAN_NAME)
protected static class IntegrationTaskSchedulerConfiguration {
@Bean(name = IntegrationContextUtils.TASK_SCHEDULER_BEAN_NAME)
@ConditionalOnBean(ThreadPoolTaskSchedulerBuilder.class)
@ConditionalOnThreading(Threading.PLATFORM)
public ThreadPoolTaskScheduler taskScheduler(ThreadPoolTaskSchedulerBuilder threadPoolTaskSchedulerBuilder) {
return threadPoolTaskSchedulerBuilder.build();
}
@Bean(name = IntegrationContextUtils.TASK_SCHEDULER_BEAN_NAME)
@ConditionalOnBean(SimpleAsyncTaskSchedulerBuilder.class)
@ConditionalOnThreading(Threading.VIRTUAL)
public SimpleAsyncTaskScheduler taskSchedulerVirtualThreads(
SimpleAsyncTaskSchedulerBuilder simpleAsyncTaskSchedulerBuilder) {
return simpleAsyncTaskSchedulerBuilder.build();
}
}
/**

View File

@ -32,6 +32,8 @@ import io.rsocket.transport.ClientTransport;
import io.rsocket.transport.netty.client.TcpClientTransport;
import org.assertj.core.api.InstanceOfAssertFactories;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledForJreRange;
import org.junit.jupiter.api.condition.JRE;
import reactor.core.publisher.Mono;
import org.springframework.beans.DirectFieldAccessor;
@ -54,9 +56,11 @@ import org.springframework.boot.jdbc.init.DataSourceScriptDatabaseInitializer;
import org.springframework.boot.sql.init.DatabaseInitializationMode;
import org.springframework.boot.sql.init.DatabaseInitializationSettings;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.boot.testsupport.assertj.SimpleAsyncTaskExecutorAssert;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.integration.annotation.IntegrationComponentScan;
import org.springframework.integration.annotation.MessagingGateway;
import org.springframework.integration.annotation.ServiceActivator;
@ -84,6 +88,7 @@ import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.rsocket.annotation.support.RSocketMessageHandler;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.SimpleAsyncTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.scheduling.support.PeriodicTrigger;
import org.springframework.test.util.ReflectionTestUtils;
@ -98,6 +103,7 @@ import static org.mockito.Mockito.mock;
* @author Artem Bilan
* @author Stephane Nicoll
* @author Vedran Pavic
* @author Yong-Hyun Kim
*/
class IntegrationAutoConfigurationTests {
@ -521,6 +527,18 @@ class IntegrationAutoConfigurationTests {
});
}
@Test
@EnabledForJreRange(min = JRE.JAVA_21)
void integrationVirtualThreadsEnabled() {
this.contextRunner.withPropertyValues("spring.threads.virtual.enabled=true")
.run((context) -> assertThat(context).hasSingleBean(TaskScheduler.class)
.getBean(IntegrationContextUtils.TASK_SCHEDULER_BEAN_NAME, TaskScheduler.class)
.isInstanceOf(SimpleAsyncTaskScheduler.class)
.satisfies((taskScheduler) -> SimpleAsyncTaskExecutorAssert
.assertThat((SimpleAsyncTaskExecutor) taskScheduler)
.usesVirtualThreads()));
}
@Configuration(proxyBeanMethods = false)
static class CustomMBeanExporter {