From a0f29edd4da9f61af8a813c66bb81546f611ec50 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Tue, 9 Jun 2020 10:56:43 +0100 Subject: [PATCH] Always initialize stompWebSocketHandlerMapping eagerly Previously, when lazy initialization was enabled, STOMP-based WebSocket messaging would not work as the stompWebSocketHandlerMapping bean was not initialized and CONNECT requests would go unanswered. This commit adds a LazyInitializationExcludeFilter that causes the stompWebSocketHandlerMapping bean to always be initialized eagerly. This triggers initialization of the WebSocket transport allowing requests to be received and processed. Fixes gh-19611 --- .../servlet/WebSocketMessagingAutoConfiguration.java | 9 ++++++++- .../WebSocketMessagingAutoConfigurationTests.java | 12 ++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/websocket/servlet/WebSocketMessagingAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/websocket/servlet/WebSocketMessagingAutoConfiguration.java index 902d37f40f..58a5c0c9c5 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/websocket/servlet/WebSocketMessagingAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/websocket/servlet/WebSocketMessagingAutoConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,7 @@ import java.util.List; import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.boot.LazyInitializationExcludeFilter; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; @@ -27,6 +28,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.messaging.converter.ByteArrayMessageConverter; import org.springframework.messaging.converter.DefaultContentTypeResolver; @@ -74,6 +76,11 @@ public class WebSocketMessagingAutoConfiguration { return false; } + @Bean + static LazyInitializationExcludeFilter eagerStompWebSocketHandlerMapping() { + return (name, definition, type) -> name.equals("stompWebSocketHandlerMapping"); + } + } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/websocket/servlet/WebSocketMessagingAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/websocket/servlet/WebSocketMessagingAutoConfigurationTests.java index c756a21f81..5c582a97bc 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/websocket/servlet/WebSocketMessagingAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/websocket/servlet/WebSocketMessagingAutoConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,6 +31,7 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.springframework.boot.LazyInitializationBeanFactoryPostProcessor; import org.springframework.boot.autoconfigure.ImportAutoConfiguration; import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration; @@ -108,6 +109,13 @@ class WebSocketMessagingAutoConfigurationTests { assertThat(new String((byte[]) result)).isEqualTo("string data"); } + @Test + void whenLazyInitializationIsEnabledThenBasicMessagingWorks() throws Throwable { + this.context.register(LazyInitializationBeanFactoryPostProcessor.class); + Object result = performStompSubscription("/app/string"); + assertThat(new String((byte[]) result)).isEqualTo("string data"); + } + @Test void customizedConverterTypesMatchDefaultConverterTypes() { List customizedConverters = getCustomizedConverters(); @@ -190,7 +198,7 @@ class WebSocketMessagingAutoConfigurationTests { stompClient.connect("ws://localhost:{port}/messaging", handler, this.context.getEnvironment().getProperty("local.server.port")); - if (!latch.await(30000, TimeUnit.SECONDS)) { + if (!latch.await(30, TimeUnit.SECONDS)) { if (failure.get() != null) { throw failure.get(); }