Skip to content

Commit ecda754

Browse files
Mazizmhalbritter
Maziz
authored andcommitted
Set virtual thread names for RabbitMQ and Pulsar
See gh-39958
1 parent f1ccc94 commit ecda754

File tree

4 files changed

+63
-5
lines changed

4 files changed

+63
-5
lines changed

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/amqp/RabbitAnnotationDrivenConfiguration.java

+12-2
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,16 @@
4747
@ConditionalOnClass(EnableRabbit.class)
4848
class RabbitAnnotationDrivenConfiguration {
4949

50+
/**
51+
* Default Name of the thread created for simple rabbit listener.
52+
*/
53+
public static final String THREADNAME_RABBIT_SIMPLE = "rabbit-simple-";
54+
55+
/**
56+
* Default Name of the thread created for direct rabbit listener.
57+
*/
58+
public static final String THREADNAME_RABBIT_DIRECT = "rabbit-direct-";
59+
5060
private final ObjectProvider<MessageConverter> messageConverter;
5161

5262
private final ObjectProvider<MessageRecoverer> messageRecoverer;
@@ -76,7 +86,7 @@ SimpleRabbitListenerContainerFactoryConfigurer simpleRabbitListenerContainerFact
7686
@ConditionalOnThreading(Threading.VIRTUAL)
7787
SimpleRabbitListenerContainerFactoryConfigurer simpleRabbitListenerContainerFactoryConfigurerVirtualThreads() {
7888
SimpleRabbitListenerContainerFactoryConfigurer configurer = simpleListenerConfigurer();
79-
configurer.setTaskExecutor(new VirtualThreadTaskExecutor());
89+
configurer.setTaskExecutor(new VirtualThreadTaskExecutor(THREADNAME_RABBIT_SIMPLE));
8090
return configurer;
8191
}
8292

@@ -105,7 +115,7 @@ DirectRabbitListenerContainerFactoryConfigurer directRabbitListenerContainerFact
105115
@ConditionalOnThreading(Threading.VIRTUAL)
106116
DirectRabbitListenerContainerFactoryConfigurer directRabbitListenerContainerFactoryConfigurerVirtualThreads() {
107117
DirectRabbitListenerContainerFactoryConfigurer configurer = directListenerConfigurer();
108-
configurer.setTaskExecutor(new VirtualThreadTaskExecutor());
118+
configurer.setTaskExecutor(new VirtualThreadTaskExecutor(THREADNAME_RABBIT_DIRECT));
109119
return configurer;
110120
}
111121

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/pulsar/PulsarAutoConfiguration.java

+13-2
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,16 @@
7373
@Import(PulsarConfiguration.class)
7474
public class PulsarAutoConfiguration {
7575

76+
/**
77+
* Default Name of the thread created for pulsar consumer.
78+
*/
79+
public static final String THREADNAME_PULSAR_CONSUMER = "pulsar-consumer-";
80+
81+
/**
82+
* Default Name of the thread created for pulsar task executor.
83+
*/
84+
public static final String THREADNAME_PULSAR_TASKEXECUTOR = "pulsar-taskexecutor-";
85+
7686
private PulsarProperties properties;
7787

7888
private PulsarPropertiesMapper propertiesMapper;
@@ -158,7 +168,7 @@ ConcurrentPulsarListenerContainerFactory<?> pulsarListenerContainerFactory(
158168
containerProperties.setSchemaResolver(schemaResolver);
159169
containerProperties.setTopicResolver(topicResolver);
160170
if (Threading.VIRTUAL.isActive(environment)) {
161-
containerProperties.setConsumerTaskExecutor(new VirtualThreadTaskExecutor());
171+
containerProperties.setConsumerTaskExecutor(new VirtualThreadTaskExecutor(THREADNAME_PULSAR_CONSUMER));
162172
}
163173
this.propertiesMapper.customizeContainerProperties(containerProperties);
164174
return new ConcurrentPulsarListenerContainerFactory<>(pulsarConsumerFactory, containerProperties);
@@ -189,7 +199,8 @@ DefaultPulsarReaderContainerFactory<?> pulsarReaderContainerFactory(PulsarReader
189199
PulsarReaderContainerProperties readerContainerProperties = new PulsarReaderContainerProperties();
190200
readerContainerProperties.setSchemaResolver(schemaResolver);
191201
if (Threading.VIRTUAL.isActive(environment)) {
192-
readerContainerProperties.setReaderTaskExecutor(new VirtualThreadTaskExecutor());
202+
readerContainerProperties
203+
.setReaderTaskExecutor(new VirtualThreadTaskExecutor(THREADNAME_PULSAR_TASKEXECUTOR));
193204
}
194205
this.propertiesMapper.customizeReaderContainerProperties(readerContainerProperties);
195206
return new DefaultPulsarReaderContainerFactory<>(pulsarReaderFactory, readerContainerProperties);

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/amqp/RabbitAutoConfigurationTests.java

+26-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import java.security.NoSuchAlgorithmException;
2020
import java.util.List;
21+
import java.util.concurrent.ThreadFactory;
2122
import java.util.concurrent.atomic.AtomicInteger;
2223

2324
import javax.net.ssl.SSLSocketFactory;
@@ -545,12 +546,36 @@ void testSimpleRabbitListenerContainerFactoryWithCustomSettings() {
545546

546547
@Test
547548
@EnabledForJreRange(min = JRE.JAVA_21)
548-
void shouldConfigureVirtualThreads() {
549+
void shouldConfigureVirtualThreadsForSimpleListener() {
549550
this.contextRunner.withPropertyValues("spring.threads.virtual.enabled=true").run((context) -> {
550551
SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory = context
551552
.getBean("rabbitListenerContainerFactory", SimpleRabbitListenerContainerFactory.class);
552553
assertThat(rabbitListenerContainerFactory).extracting("taskExecutor")
553554
.isInstanceOf(VirtualThreadTaskExecutor.class);
555+
final var taskExecutor = ReflectionTestUtils.getField(rabbitListenerContainerFactory, "taskExecutor");
556+
final var virtualThread = ReflectionTestUtils.getField(taskExecutor, "virtualThreadFactory");
557+
final var threadCreated = ((ThreadFactory) virtualThread).newThread(mock(Runnable.class));
558+
assertThat(threadCreated.getName())
559+
.containsPattern(RabbitAnnotationDrivenConfiguration.THREADNAME_RABBIT_SIMPLE + "[0-9]*");
560+
561+
});
562+
}
563+
564+
@Test
565+
@EnabledForJreRange(min = JRE.JAVA_21)
566+
void shouldConfigureVirtualThreadsForDirectListener() {
567+
this.contextRunner.withPropertyValues("spring.threads.virtual.enabled=true").run((context) -> {
568+
DirectRabbitListenerContainerFactoryConfigurer rabbitListenerContainerFactory = context.getBean(
569+
"directRabbitListenerContainerFactoryConfigurer",
570+
DirectRabbitListenerContainerFactoryConfigurer.class);
571+
assertThat(rabbitListenerContainerFactory).extracting("taskExecutor")
572+
.isInstanceOf(VirtualThreadTaskExecutor.class);
573+
final var taskExecutor = ReflectionTestUtils.getField(rabbitListenerContainerFactory, "taskExecutor");
574+
final var virtualThread = ReflectionTestUtils.getField(taskExecutor, "virtualThreadFactory");
575+
final var threadCreated = ((ThreadFactory) virtualThread).newThread(mock(Runnable.class));
576+
assertThat(threadCreated.getName())
577+
.containsPattern(RabbitAnnotationDrivenConfiguration.THREADNAME_RABBIT_DIRECT + "[0-9]*");
578+
554579
});
555580
}
556581

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/pulsar/PulsarAutoConfigurationTests.java

+12
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import java.util.ArrayList;
2020
import java.util.List;
21+
import java.util.concurrent.ThreadFactory;
2122
import java.util.concurrent.TimeUnit;
2223

2324
import com.github.benmanes.caffeine.cache.Caffeine;
@@ -69,6 +70,7 @@
6970
import org.springframework.pulsar.core.ReaderBuilderCustomizer;
7071
import org.springframework.pulsar.core.SchemaResolver;
7172
import org.springframework.pulsar.core.TopicResolver;
73+
import org.springframework.test.util.ReflectionTestUtils;
7274

7375
import static org.assertj.core.api.Assertions.assertThat;
7476
import static org.mockito.Mockito.mock;
@@ -506,6 +508,11 @@ void whenVirtualThreadsAreEnabledOnJava21AndLaterListenerContainerShouldUseVirtu
506508
.getBean(ConcurrentPulsarListenerContainerFactory.class);
507509
assertThat(factory.getContainerProperties().getConsumerTaskExecutor())
508510
.isInstanceOf(VirtualThreadTaskExecutor.class);
511+
final var taskExecutor = factory.getContainerProperties().getConsumerTaskExecutor();
512+
final var virtualThread = ReflectionTestUtils.getField(taskExecutor, "virtualThreadFactory");
513+
final var threadCreated = ((ThreadFactory) virtualThread).newThread(mock(Runnable.class));
514+
assertThat(threadCreated.getName())
515+
.containsPattern(PulsarAutoConfiguration.THREADNAME_PULSAR_CONSUMER + "[0-9]*");
509516
});
510517
}
511518

@@ -561,6 +568,11 @@ void whenVirtualThreadsAreEnabledOnJava21AndLaterReaderShouldUseVirtualThreads()
561568
.getBean(DefaultPulsarReaderContainerFactory.class);
562569
assertThat(factory.getContainerProperties().getReaderTaskExecutor())
563570
.isInstanceOf(VirtualThreadTaskExecutor.class);
571+
final var taskExecutor = factory.getContainerProperties().getReaderTaskExecutor();
572+
final var virtualThread = ReflectionTestUtils.getField(taskExecutor, "virtualThreadFactory");
573+
final var threadCreated = ((ThreadFactory) virtualThread).newThread(mock(Runnable.class));
574+
assertThat(threadCreated.getName())
575+
.containsPattern(PulsarAutoConfiguration.THREADNAME_PULSAR_TASKEXECUTOR + "[0-9]*");
564576
});
565577
}
566578

0 commit comments

Comments
 (0)