Search code examples
javascriptjavastompspring-websocket

WebSocket connection failing using STOMP.js


I'm using Spring Boot WebSockets, STOMP.js, and JQuery to develop a short training project. Sadly I seem to have missed some crucial point while following guides and the official documentation because as soon as I try to activate my StompJs.Client object my browser console prints this error:

WebSocket connection to 'ws://localhost:8080/game-websocket' failed: https://cdn.jsdelivr.net/npm/@stomp/[email protected]/bundles/stomp.umd.min.js

I suppose I am missing an extremely obvious point here, but after trying to understand the source of the error for some time now I can't seem to advance. Now follows my HTML-frontend, my JavaScript (Gamescript.js), the WebSocket configuration Java class and finally my controller Java class.

First, my HTML-Frontend:

<!DOCTYPE html>
<html lang="en">

    <head>
        <meta charset="UTF-8">
        <title>Battleships</title>
        <link href="/static/GameDesign.css" rel="stylesheet">
        <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/@stomp/[email protected]/bundles/stomp.umd.min.js"></script>
        <script src="/static/GameScript.js"></script>

    </head>

    <body>

        <!-- generates the (for this session) hidden enemy board, that consists of 100 buttons with
         according IDs (e-presign), beginning from the bottom-left corner and counting rows first -->
        <script>
            document.write("<form><table>");
            for(var i=9; i>=0; i--){
                document.write("<tr>");
                for(var k=0; k<10; k++){
                    document.write("<td><button type=\"submit\" id=\"e" + k + i + "\"></button></td>");
                }
                document.write("</tr>");
            }
            document.write("</table></form>");
        </script>

        <!-- generates the own board of this session, that consists of 100 div-elements with
         according IDs (o-presign), beginning from the bottom-left corner and counting rows first -->
        <script>
            document.write("<table>");
            for(var i=9; i>=0; i--){
                document.write("<tr>");
                for(var k=0; k<10; k++){
                    document.write("<td><div id=\"o" + k + i + "\"></div></td>");
                }
                document.write("</tr>");
            }
            document.write("</table>");
        </script>

    </body>

</html>

Now my JavaScript (GameScript.js):

const stompClient = new StompJs.Client({
    brokerURL: 'ws://localhost:8080/game-websocket'
});

function connect(){
    stompClient.activate();
}

function sendID(){
     stompClient.publish("/app/provideSession", {}, "kevin");
}

stompClient.onConnect = (frame) => {
    stompClient.subscribe("/queue/sessionResponse", (message) => {
        console.log(message);
    });
}

$(function () {
    $("form").on('submit', (e) => e.preventDefault());
    $( "#e00" ).click(() => connect());
    $( "#e99" ).click(() => sendID());
});

Now my Websocket configuration java class:

package com.md.battleships;

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/game-websocket");
    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.setApplicationDestinationPrefixes("/app");
        config.enableSimpleBroker("/queue");
    }
}

And finally my Java controller class:

package com.md.battleships;

import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;

@Controller
public class GameController {

    @MessageMapping("/provideSession")
    @SendTo("/sessionResponse")
    public String handshake (String session) throws Exception{
        System.out.println(session);
        return "kevoon (Entwicklung von Kevin)";
    }
}

Solution

  • Okay so apparently it's a routing issue. IntelliJ Community doesn't support Spring WebSockets, so it showed me a warning for my css and script import in my frontend-HTML. Those two imports need to get the "/static" part removed so that the server finds the userscript, the css and my STOMP layer while running on port 8080.

    I'm pretty sure im just scratching the surface here, so i'm happy if someone can explain the issue i somehow solved in more detail to me.