Add @Order to WebSocketMessageConverterConfiguration

Add `@Order` to `WebSocketMessageConverterConfiguration` so that custom
`WebSocketMessageBrokerConfigurer` implementations can be added before
or after ours.

Fixes gh-42924
This commit is contained in:
Phillip Webb 2024-11-01 17:49:38 -07:00
parent c2ab2ddd6c
commit 06f0b91429
2 changed files with 40 additions and 0 deletions

View File

@ -32,6 +32,7 @@ import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
import org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.messaging.converter.ByteArrayMessageConverter;
import org.springframework.messaging.converter.DefaultContentTypeResolver;
@ -60,6 +61,7 @@ public class WebSocketMessagingAutoConfiguration {
@Configuration(proxyBeanMethods = false)
@ConditionalOnBean({ DelegatingWebSocketMessageBrokerConfiguration.class, ObjectMapper.class })
@ConditionalOnClass({ ObjectMapper.class, AbstractMessageBrokerConfiguration.class })
@Order(0)
static class WebSocketMessageConverterConfiguration implements WebSocketMessageBrokerConfigurer {
private final ObjectMapper objectMapper;

View File

@ -29,6 +29,7 @@ import java.util.concurrent.atomic.AtomicReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.tomcat.websocket.WsWebSocketContainer;
import org.assertj.core.api.InstanceOfAssertFactories;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@ -40,12 +41,15 @@ import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
import org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration;
import org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration.WebSocketMessageConverterConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.core.task.TaskExecutor;
@ -62,6 +66,7 @@ import org.springframework.messaging.simp.stomp.StompSession;
import org.springframework.messaging.simp.stomp.StompSessionHandler;
import org.springframework.messaging.simp.stomp.StompSessionHandlerAdapter;
import org.springframework.security.util.FieldUtils;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.socket.client.standard.StandardWebSocketClient;
@ -162,6 +167,26 @@ class WebSocketMessagingAutoConfigurationTests {
assertThat(executor).isEqualTo(expectedExecutor);
}
@Test
void webSocketMessageBrokerConfigurerOrdering() throws Throwable {
TestPropertyValues.of("server.port:0", "spring.jackson.serialization.indent-output:true").applyTo(this.context);
this.context.register(WebSocketMessagingConfiguration.class, CustomLowWebSocketMessageBrokerConfigurer.class,
CustomHighWebSocketMessageBrokerConfigurer.class);
this.context.refresh();
DelegatingWebSocketMessageBrokerConfiguration delegatingConfiguration = this.context
.getBean(DelegatingWebSocketMessageBrokerConfiguration.class);
CustomHighWebSocketMessageBrokerConfigurer high = this.context
.getBean(CustomHighWebSocketMessageBrokerConfigurer.class);
WebSocketMessageConverterConfiguration autoConfiguration = this.context
.getBean(WebSocketMessagingAutoConfiguration.WebSocketMessageConverterConfiguration.class);
WebSocketMessagingConfiguration configuration = this.context.getBean(WebSocketMessagingConfiguration.class);
CustomLowWebSocketMessageBrokerConfigurer low = this.context
.getBean(CustomLowWebSocketMessageBrokerConfigurer.class);
assertThat(delegatingConfiguration).extracting("configurers")
.asInstanceOf(InstanceOfAssertFactories.LIST)
.containsExactly(high, autoConfiguration, configuration, low);
}
private List<MessageConverter> getCustomizedConverters() {
List<MessageConverter> customizedConverters = new ArrayList<>();
WebSocketMessagingAutoConfiguration.WebSocketMessageConverterConfiguration configuration = new WebSocketMessagingAutoConfiguration.WebSocketMessageConverterConfiguration(
@ -246,6 +271,7 @@ class WebSocketMessagingAutoConfigurationTests {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/messaging").withSockJS();
}
@ -271,6 +297,18 @@ class WebSocketMessagingAutoConfigurationTests {
}
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
static class CustomHighWebSocketMessageBrokerConfigurer implements WebSocketMessageBrokerConfigurer {
}
@Component
@Order(Ordered.LOWEST_PRECEDENCE)
static class CustomLowWebSocketMessageBrokerConfigurer implements WebSocketMessageBrokerConfigurer {
}
@Controller
static class MessagingController {