From 10644de954bcf7946bd691ec51d71aba880418f0 Mon Sep 17 00:00:00 2001 From: jsgrah-spring Date: Thu, 12 Jan 2023 18:55:18 +0100 Subject: [PATCH] JAVA-14459, GitHub Issue: Reactive WebSocket App example no longer works. (#13272) Co-authored-by: jogra --- .../spring-5-reactive/pom.xml | 10 ++++- .../reactive/Spring5ReactiveApplication.java | 3 +- .../ReactiveWebSocketApplication.java | 16 +++++++- .../ReactiveWebSocketConfiguration.java | 34 ++++++++++++++-- .../websocket/WebSocketController.java | 40 +++++++++++++++++++ .../src/main/resources/application.properties | 3 +- 6 files changed, 98 insertions(+), 8 deletions(-) create mode 100644 spring-reactive-modules/spring-5-reactive/src/main/java/com/baeldung/websocket/WebSocketController.java diff --git a/spring-reactive-modules/spring-5-reactive/pom.xml b/spring-reactive-modules/spring-5-reactive/pom.xml index 5eb98eb106..212281b6f9 100644 --- a/spring-reactive-modules/spring-5-reactive/pom.xml +++ b/spring-reactive-modules/spring-5-reactive/pom.xml @@ -26,7 +26,11 @@ org.springframework.boot - spring-boot-starter-webflux + spring-boot-starter-integration + + + org.springframework.boot + spring-boot-starter-websocket javax.json.bind @@ -111,6 +115,10 @@ org.apache.httpcomponents httpclient + + io.netty + netty-all + diff --git a/spring-reactive-modules/spring-5-reactive/src/main/java/com/baeldung/reactive/Spring5ReactiveApplication.java b/spring-reactive-modules/spring-5-reactive/src/main/java/com/baeldung/reactive/Spring5ReactiveApplication.java index a8cd18c470..ef862dd957 100644 --- a/spring-reactive-modules/spring-5-reactive/src/main/java/com/baeldung/reactive/Spring5ReactiveApplication.java +++ b/spring-reactive-modules/spring-5-reactive/src/main/java/com/baeldung/reactive/Spring5ReactiveApplication.java @@ -2,8 +2,9 @@ package com.baeldung.reactive; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; -@SpringBootApplication +@SpringBootApplication(exclude = { RedisAutoConfiguration.class }) public class Spring5ReactiveApplication{ public static void main(String[] args) { diff --git a/spring-reactive-modules/spring-5-reactive/src/main/java/com/baeldung/websocket/ReactiveWebSocketApplication.java b/spring-reactive-modules/spring-5-reactive/src/main/java/com/baeldung/websocket/ReactiveWebSocketApplication.java index 0e71673df6..148dd07510 100644 --- a/spring-reactive-modules/spring-5-reactive/src/main/java/com/baeldung/websocket/ReactiveWebSocketApplication.java +++ b/spring-reactive-modules/spring-5-reactive/src/main/java/com/baeldung/websocket/ReactiveWebSocketApplication.java @@ -2,8 +2,22 @@ package com.baeldung.websocket; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; +import org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration; +import org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration; +import org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration; +import org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration; +import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration; +import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; -@SpringBootApplication +@SpringBootApplication(exclude = { + SecurityAutoConfiguration.class, + UserDetailsServiceAutoConfiguration.class, + ReactiveSecurityAutoConfiguration.class, + ReactiveUserDetailsServiceAutoConfiguration.class, + ReactiveOAuth2ClientAutoConfiguration.class, + WebMvcAutoConfiguration.class, + RedisAutoConfiguration.class}) public class ReactiveWebSocketApplication { public static void main(String[] args) { SpringApplication.run(ReactiveWebSocketApplication.class, args); diff --git a/spring-reactive-modules/spring-5-reactive/src/main/java/com/baeldung/websocket/ReactiveWebSocketConfiguration.java b/spring-reactive-modules/spring-5-reactive/src/main/java/com/baeldung/websocket/ReactiveWebSocketConfiguration.java index 43a98d068d..8ebd6118b2 100644 --- a/spring-reactive-modules/spring-5-reactive/src/main/java/com/baeldung/websocket/ReactiveWebSocketConfiguration.java +++ b/spring-reactive-modules/spring-5-reactive/src/main/java/com/baeldung/websocket/ReactiveWebSocketConfiguration.java @@ -10,19 +10,25 @@ import org.springframework.context.annotation.Configuration; import org.springframework.web.reactive.HandlerMapping; import org.springframework.web.reactive.handler.SimpleUrlHandlerMapping; import org.springframework.web.reactive.socket.WebSocketHandler; +import org.springframework.web.reactive.socket.server.WebSocketService; +import org.springframework.web.reactive.socket.server.support.HandshakeWebSocketService; +import org.springframework.web.reactive.socket.server.upgrade.TomcatRequestUpgradeStrategy; +import org.springframework.web.socket.config.annotation.EnableWebSocket; import org.springframework.web.reactive.socket.server.support.WebSocketHandlerAdapter; +import org.springframework.web.socket.server.standard.ServerEndpointExporter; @Configuration +@EnableWebSocket public class ReactiveWebSocketConfiguration { @Autowired @Qualifier("ReactiveWebSocketHandler") - private WebSocketHandler webSocketHandler; + private ReactiveWebSocketHandler reactiveWebSocketHandler; @Bean - public HandlerMapping webSocketHandlerMapping() { + public HandlerMapping reactiveWebSocketHandlerMapping() { Map map = new HashMap<>(); - map.put("/event-emitter", webSocketHandler); + map.put("/event-emitter", reactiveWebSocketHandler); SimpleUrlHandlerMapping handlerMapping = new SimpleUrlHandlerMapping(); handlerMapping.setOrder(1); @@ -32,6 +38,26 @@ public class ReactiveWebSocketConfiguration { @Bean public WebSocketHandlerAdapter handlerAdapter() { - return new WebSocketHandlerAdapter(); + return new WebSocketHandlerAdapter(webSocketService()); + } + + @Bean + public WebSocketService webSocketService() { + TomcatRequestUpgradeStrategy tomcatRequestUpgradeStrategy = new TomcatRequestUpgradeStrategy(); + tomcatRequestUpgradeStrategy.setMaxSessionIdleTimeout(10000L); + tomcatRequestUpgradeStrategy.setAsyncSendTimeout(10000L); + return new HandshakeWebSocketService(tomcatRequestUpgradeStrategy); + } + + @Bean + public ServerEndpointExporter serverEndpointExporter() { + ServerEndpointExporter serverEndpointExporter = new ServerEndpointExporter(); + + /** + * Add one or more classes annotated with `@ServerEndpoint`. + */ + serverEndpointExporter.setAnnotatedEndpointClasses(WebSocketController.class); + + return serverEndpointExporter; } } \ No newline at end of file diff --git a/spring-reactive-modules/spring-5-reactive/src/main/java/com/baeldung/websocket/WebSocketController.java b/spring-reactive-modules/spring-5-reactive/src/main/java/com/baeldung/websocket/WebSocketController.java new file mode 100644 index 0000000000..bf4a463ae6 --- /dev/null +++ b/spring-reactive-modules/spring-5-reactive/src/main/java/com/baeldung/websocket/WebSocketController.java @@ -0,0 +1,40 @@ +package com.baeldung.websocket; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.websocket.*; +import javax.websocket.server.ServerEndpoint; +import java.io.IOException; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +@ServerEndpoint("/event-emitter") +public class WebSocketController { + + private static final Logger LOGGER = LoggerFactory.getLogger(WebSocketController.class); + @OnOpen + public void onOpen(Session session, EndpointConfig endpointConfig) throws IOException { + // Get session and WebSocket connection + session.setMaxIdleTimeout(0); + LOGGER.info("Get session and WebSocket connection"); + } + + @OnMessage + public void onMessage(String message, Session session) throws IOException { + // Handle new messages + LOGGER.info("Handle new messages -> {}", message ); + } + + @OnClose + public void onClose(Session session) throws IOException { + // WebSocket connection closes + LOGGER.info("WebSocket connection closes"); + } + + @OnError + public void onError(Session session, Throwable throwable) { + // Do error handling here + LOGGER.info("Do error handling here"); + } +} diff --git a/spring-reactive-modules/spring-5-reactive/src/main/resources/application.properties b/spring-reactive-modules/spring-5-reactive/src/main/resources/application.properties index 4b49e8e8a2..dfe4a4d994 100644 --- a/spring-reactive-modules/spring-5-reactive/src/main/resources/application.properties +++ b/spring-reactive-modules/spring-5-reactive/src/main/resources/application.properties @@ -1 +1,2 @@ -logging.level.root=INFO \ No newline at end of file +logging.level.root=INFO +server.tomcat.max-keep-alive-requests=1 \ No newline at end of file