Harmonize WebSocket message broker to use Executor

This commit harmonizes the configuration of the WebSocket message
broker to use Executor rather than TaskExecutor as only the former
is enforced. This lets custom configuration to use a wider range
of implementations.

Closes gh-32129
This commit is contained in:
Stéphane Nicoll
2024-01-26 11:30:22 +01:00
parent 2fc8b13dd5
commit f526b23fd7
5 changed files with 78 additions and 79 deletions

View File

@@ -16,12 +16,12 @@
package org.springframework.messaging.simp.config;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
import java.util.function.Supplier;
import org.junit.jupiter.api.Test;
import org.springframework.core.task.TaskExecutor;
import org.springframework.messaging.support.ChannelInterceptor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
@@ -38,20 +38,20 @@ import static org.mockito.Mockito.verifyNoInteractions;
*/
class ChannelRegistrationTests {
private final Supplier<TaskExecutor> fallback = mock();
private final Supplier<Executor> fallback = mock();
private final Consumer<TaskExecutor> customizer = mock();
private final Consumer<Executor> customizer = mock();
@Test
void emptyRegistrationUsesFallback() {
TaskExecutor fallbackTaskExecutor = mock(TaskExecutor.class);
given(this.fallback.get()).willReturn(fallbackTaskExecutor);
Executor fallbackExecutor = mock(Executor.class);
given(this.fallback.get()).willReturn(fallbackExecutor);
ChannelRegistration registration = new ChannelRegistration();
assertThat(registration.hasTaskExecutor()).isFalse();
TaskExecutor actual = registration.getTaskExecutor(this.fallback, this.customizer);
assertThat(actual).isSameAs(fallbackTaskExecutor);
assertThat(registration.hasExecutor()).isFalse();
Executor actual = registration.getExecutor(this.fallback, this.customizer);
assertThat(actual).isSameAs(fallbackExecutor);
verify(this.fallback).get();
verify(this.customizer).accept(fallbackTaskExecutor);
verify(this.customizer).accept(fallbackExecutor);
}
@Test
@@ -65,45 +65,45 @@ class ChannelRegistrationTests {
void taskRegistrationCreatesDefaultInstance() {
ChannelRegistration registration = new ChannelRegistration();
registration.taskExecutor();
assertThat(registration.hasTaskExecutor()).isTrue();
TaskExecutor taskExecutor = registration.getTaskExecutor(this.fallback, this.customizer);
assertThat(taskExecutor).isInstanceOf(ThreadPoolTaskExecutor.class);
assertThat(registration.hasExecutor()).isTrue();
Executor executor = registration.getExecutor(this.fallback, this.customizer);
assertThat(executor).isInstanceOf(ThreadPoolTaskExecutor.class);
verifyNoInteractions(this.fallback);
verify(this.customizer).accept(taskExecutor);
verify(this.customizer).accept(executor);
}
@Test
void taskRegistrationWithExistingThreadPoolTaskExecutor() {
ThreadPoolTaskExecutor existingTaskExecutor = mock(ThreadPoolTaskExecutor.class);
ThreadPoolTaskExecutor existingExecutor = mock(ThreadPoolTaskExecutor.class);
ChannelRegistration registration = new ChannelRegistration();
registration.taskExecutor(existingTaskExecutor);
assertThat(registration.hasTaskExecutor()).isTrue();
TaskExecutor taskExecutor = registration.getTaskExecutor(this.fallback, this.customizer);
assertThat(taskExecutor).isSameAs(existingTaskExecutor);
registration.taskExecutor(existingExecutor);
assertThat(registration.hasExecutor()).isTrue();
Executor executor = registration.getExecutor(this.fallback, this.customizer);
assertThat(executor).isSameAs(existingExecutor);
verifyNoInteractions(this.fallback);
verify(this.customizer).accept(taskExecutor);
verify(this.customizer).accept(executor);
}
@Test
void configureExecutor() {
ChannelRegistration registration = new ChannelRegistration();
TaskExecutor taskExecutor = mock(TaskExecutor.class);
registration.executor(taskExecutor);
assertThat(registration.hasTaskExecutor()).isTrue();
TaskExecutor taskExecutor1 = registration.getTaskExecutor(this.fallback, this.customizer);
assertThat(taskExecutor1).isSameAs(taskExecutor);
Executor executor = mock(Executor.class);
registration.executor(executor);
assertThat(registration.hasExecutor()).isTrue();
Executor actualExecutor = registration.getExecutor(this.fallback, this.customizer);
assertThat(actualExecutor).isSameAs(executor);
verifyNoInteractions(this.fallback, this.customizer);
}
@Test
void configureExecutorTakesPrecedenceOverTaskRegistration() {
ChannelRegistration registration = new ChannelRegistration();
TaskExecutor taskExecutor = mock(TaskExecutor.class);
registration.executor(taskExecutor);
Executor executor = mock(Executor.class);
registration.executor(executor);
ThreadPoolTaskExecutor ignored = mock(ThreadPoolTaskExecutor.class);
registration.taskExecutor(ignored);
assertThat(registration.hasTaskExecutor()).isTrue();
assertThat(registration.getTaskExecutor(this.fallback, this.customizer)).isSameAs(taskExecutor);
assertThat(registration.hasExecutor()).isTrue();
assertThat(registration.getExecutor(this.fallback, this.customizer)).isSameAs(executor);
verifyNoInteractions(ignored, this.fallback, this.customizer);
}

View File

@@ -22,6 +22,7 @@ import java.util.List;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import org.junit.jupiter.api.Test;
@@ -31,7 +32,6 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.StaticApplicationContext;
import org.springframework.core.Ordered;
import org.springframework.core.task.TaskExecutor;
import org.springframework.lang.Nullable;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
@@ -599,20 +599,20 @@ class MessageBrokerConfigurationTests {
@Override
@Bean
public AbstractSubscribableChannel clientInboundChannel(TaskExecutor clientInboundChannelExecutor) {
public AbstractSubscribableChannel clientInboundChannel(Executor clientInboundChannelExecutor) {
return new TestChannel();
}
@Override
@Bean
public AbstractSubscribableChannel clientOutboundChannel(TaskExecutor clientOutboundChannelExecutor) {
public AbstractSubscribableChannel clientOutboundChannel(Executor clientOutboundChannelExecutor) {
return new TestChannel();
}
@Override
@Bean
public AbstractSubscribableChannel brokerChannel(AbstractSubscribableChannel clientInboundChannel,
AbstractSubscribableChannel clientOutboundChannel, TaskExecutor brokerChannelExecutor) {
AbstractSubscribableChannel clientOutboundChannel, Executor brokerChannelExecutor) {
return new TestChannel();
}
}
@@ -688,21 +688,21 @@ class MessageBrokerConfigurationTests {
@Override
@Bean
public AbstractSubscribableChannel clientInboundChannel(TaskExecutor clientInboundChannelExecutor) {
public AbstractSubscribableChannel clientInboundChannel(Executor clientInboundChannelExecutor) {
// synchronous
return new ExecutorSubscribableChannel(null);
}
@Override
@Bean
public AbstractSubscribableChannel clientOutboundChannel(TaskExecutor clientOutboundChannelExecutor) {
public AbstractSubscribableChannel clientOutboundChannel(Executor clientOutboundChannelExecutor) {
return new TestChannel();
}
@Override
@Bean
public AbstractSubscribableChannel brokerChannel(AbstractSubscribableChannel clientInboundChannel,
AbstractSubscribableChannel clientOutboundChannel, TaskExecutor brokerChannelExecutor) {
AbstractSubscribableChannel clientOutboundChannel, Executor brokerChannelExecutor) {
// synchronous
return new ExecutorSubscribableChannel(null);
}