diff --git a/dev/io.openliberty.springboot.fat30.websocket.app/build.gradle b/dev/io.openliberty.springboot.fat30.websocket.app/build.gradle index d29f71a99f1e..6c49d5faddf3 100644 --- a/dev/io.openliberty.springboot.fat30.websocket.app/build.gradle +++ b/dev/io.openliberty.springboot.fat30.websocket.app/build.gradle @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017, 2023 IBM Corporation and others. + * Copyright (c) 2017, 2025 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at @@ -13,7 +13,7 @@ // https://plugins.gradle.org/plugin/org.springframework.boot plugins { - id 'org.springframework.boot' version '3.0.7' + id 'org.springframework.boot' version '3.4.4' } apply from: '../wlp-gradle/subprojects/spring.gradle' def sv = springVersions[ '3.0' ] @@ -28,5 +28,8 @@ sourceCompatibility = 17 apply from: '../wlp-gradle/subprojects/maven-central-mirror.gradle' dependencies { - implementation('org.springframework.boot:spring-boot-starter-websocket' + ':' + sv['springBoot']) + implementation('org.springframework.boot:spring-boot-starter-websocket') { + exclude module: 'spring-boot-starter-tomcat' //Temporarily excluding tomcat starter till it is removed in SpringBootThinUtil + } + compileOnly('org.springframework.boot:spring-boot-starter-tomcat') } diff --git a/dev/io.openliberty.springboot.fat30.websocket.app/src/main/java/com/ibm/ws/springboot/fat30/websocket/app/TestApplication.java b/dev/io.openliberty.springboot.fat30.websocket.app/src/main/java/com/ibm/ws/springboot/fat30/websocket/app/TestApplication.java index 39fa1687d7c6..f432b96548e9 100644 --- a/dev/io.openliberty.springboot.fat30.websocket.app/src/main/java/com/ibm/ws/springboot/fat30/websocket/app/TestApplication.java +++ b/dev/io.openliberty.springboot.fat30.websocket.app/src/main/java/com/ibm/ws/springboot/fat30/websocket/app/TestApplication.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2018,2023 IBM Corporation and others. + * Copyright (c) 2018,2025 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at @@ -18,13 +18,20 @@ import org.springframework.context.annotation.Bean; import org.springframework.web.socket.config.annotation.EnableWebSocket; import org.springframework.web.socket.server.standard.ServerEndpointExporter; +import org.springframework.web.socket.config.annotation.WebSocketConfigurer; +import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; +import org.springframework.web.socket.server.support.AbstractHandshakeHandler; +import org.springframework.web.socket.server.support.DefaultHandshakeHandler; +import org.springframework.web.socket.handler.TextWebSocketHandler; +import org.springframework.web.socket.TextMessage; +import org.springframework.web.socket.WebSocketSession; import com.ibm.ws.springboot.fat30.websocket.echo.ServerEchoWebSocketEndpoint; @SpringBootApplication @EnableWebSocket -public class TestApplication{ +public class TestApplication implements WebSocketConfigurer { public static void main(String[] args) { SpringApplication.run(TestApplication.class, args); @@ -40,4 +47,23 @@ public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } + @Override + public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { + registry.addHandler(customWebSocketHandler(), "/customHandler").setHandshakeHandler(customHandshakeHandler()); + } + + @Bean + public TextWebSocketHandler customWebSocketHandler() { + return new TextWebSocketHandler() { + @Override + public void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { + session.sendMessage(new TextMessage("Did you say: " + message.getPayload())); + } + }; + } + + @Bean + public AbstractHandshakeHandler customHandshakeHandler() { + return new DefaultHandshakeHandler(); + } } diff --git a/dev/io.openliberty.springboot.fat30_fat/fat/src/com/ibm/ws/springboot/support/fat/WebSocketTests30.java b/dev/io.openliberty.springboot.fat30_fat/fat/src/com/ibm/ws/springboot/support/fat/WebSocketTests30.java index 4af6b239d882..a9eb3eb68379 100644 --- a/dev/io.openliberty.springboot.fat30_fat/fat/src/com/ibm/ws/springboot/support/fat/WebSocketTests30.java +++ b/dev/io.openliberty.springboot.fat30_fat/fat/src/com/ibm/ws/springboot/support/fat/WebSocketTests30.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2018,2023 IBM Corporation and others. + * Copyright (c) 2018,2025 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at @@ -27,6 +27,7 @@ import jakarta.websocket.Session; import jakarta.websocket.WebSocketContainer; +import org.junit.AfterClass; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -86,6 +87,28 @@ public void testEchoWebSocket30() throws Exception { assertEquals("Expected message from server not found", "Did you say: Hello World", clientEndpoint.getMessageFromServer()); } + /** + * Test websocket using a custom websocket configurer. + * + * The application registers a custom websocket handler and a abstract handshake handler. + * The org.springframework.web.socket.server.support.AbstractHandshakeHandler looksup websphere websocket code which is now being removed in spring framework 7.x. + * This test should fail for future Spring Boot versions using spring framework 7.x, we might have to use the websocket-2.2 feature and do some implementation changes if + * required. + * + * @throws Exception + */ + @Test + public void testEchoWithCustomWebsocketHandler() throws Exception { + Log.info(getClass(), "testEchoWithCustomWebsocketHandler", wsContainer.toString()); + Session session = wsContainer.connectToServer(clientEndpoint, new URI("ws://" + server.getHostname() + ":" + server.getHttpDefaultPort() + "/customHandler")); + assertNotNull("Session cannot be null", session); + assertTrue("Session is not open", session.isOpen()); + CountDownLatch latch = new CountDownLatch(1); + clientEndpoint.sendMessage("Hello Websocket", latch); + assertTrue(latch.await(5, TimeUnit.SECONDS)); + assertEquals("Expected message from server not found", "Did you say: Hello Websocket", clientEndpoint.getMessageFromServer()); + } + @Override public Set getFeatures() { return new HashSet<>(Arrays.asList("springBoot-3.0", "servlet-6.0", "websocket-2.1")); @@ -96,4 +119,11 @@ public String getApplication() { return SPRING_BOOT_30_APP_WEBSOCKET; } + @AfterClass + public static void stopTestServer() throws Exception { + //[WARNING ] SRVE8094W: WARNING: Cannot set header. Response already committed. Stack trace of errant attempt to set header: + //at com.ibm.ws.webcontainer.srt.SRTServletResponse.setHeader(SRTServletResponse.java:1845) + server.stopServer(true, "SRVE8094W"); + } + }