Search code examples
grailsjava-websocket

Connection to WebSocket Failed: unexpected response code : 404


iam trying to create a chat with javax.websocket. i am using grails. 3.0

this is my controller

package chatting

import javax.websocket.server.ServerEndpoint;
import javax.websocket.OnMessage;

@ServerEndpoint("/echo")
public class WebsocketHomeController {

    def index() { }

    @OnMessage


    public String echo(String incomingMessage) {
            return "I got this (" + incomingMessage + ")"
            + " so I am sending it back !";
        }
    }

this is my index.gsp

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

    <title>Web Socket JavaScript Echo Client</title>
    <script language="javascript" type="text/javascript">
        var echo_websocket;
        function init() {
            output = document.getElementById("output");
        }
        function send_echo() {
            var wsUri = "ws://192.168.1.2:8080/WebsocketHome/echo";
            writeToScreen("Connecting to " + wsUri);
            echo_websocket = new WebSocket(wsUri);
            echo_websocket.onopen = function (evt) {
                writeToScreen("Connected !");
                doSend(textID.value);
            };
            echo_websocket.onmessage = function (evt) {
                writeToScreen("Received message: " + evt.data);
                echo_websocket.close();
            };
            echo_websocket.onerror = function (evt) {
                writeToScreen('<span style="color: red;">ERROR:</span> '
                + evt.data);
                echo_websocket.close();
            };
        }
        function showErrorInfo(e) {
            alert('Error connecting socket'+e);
        }

        function doSend(message) {
            echo_websocket.send(message);
            writeToScreen("Sent message: " + message);
        }
        function writeToScreen(message) {
            var pre = document.createElement("p");
            pre.style.wordWrap = "break-word";
            pre.innerHTML = message;
            output.appendChild(pre);
        }
        window.addEventListener("load", init, false);
    </script>
</head>
<body>
    <h1>Echo Server</h1>
    <div style="text-align: left;">
        <form action="">
            <input onclick="send_echo()" value="Press to send"
                   type="button">
            <input id="textID" name="message" value="Hello Web Sockets"
                   type="text">
            <br>
        </form>
    </div>
    <div id="output"></div>
</body>
</html>

this is the result..

enter image description here

i have no idea ..why i get this error...

i tried to debug my code like this..

public String echo(String incomingMessage) {
println "this is runing"
return "I got this (" + incomingMessage + ")"
+ " so I am sending it back !";
}

then i get "this is running" in my console log

what must i do?


Solution

  • To add a listener in grails 3:

    1. Add doWithSpring closure to your ìnit/appName/Application.groovy

    https://github.com/vahidhedayati/testwschatapp/blob/master/grails-app/init/testwschatapp/Application.groovy#L7-L11

    Closure doWithSpring() {
        {->
            myChatConfig DefaultChatConfig
        }
    }
    

    Create a file in grails-app/init/{appname}/DefaultChatConfig.groovy

    https://github.com/vahidhedayati/testwschatapp/blob/master/grails-app/init/testwschatapp/DefaultWsChatConfig.groovy

    package myappName
    
    import path.to.WebsocketHomeController
    
    import org.springframework.boot.context.embedded.ServletContextInitializer
    import org.springframework.context.annotation.Bean
    
    import javax.servlet.ServletContext
    import javax.servlet.ServletException
    
    class DefaultChatConfig {
    
        @Bean
        public ServletContextInitializer myInitializer() {
            return new ServletContextInitializer() {
                @Override
                public void onStartup(ServletContext servletContext) throws ServletException {
                    ServletContext.addListener(WebsocketHomeController)
                }
            }
        }
    
    }
    

    You will need to sort out the import line at the top of the 2nd file import path.to.WebsocketHomeController

    By the way in one my comments on the chat plugin I suggested you could make your own interfaces. By that I meant to interact with the plugin. If the plugin is doing a lot of the functionality for you but lets say you wish to manage your own users.

    You could just write services in your own app that call the chat classes to view/edit/delete etc. The very same way I have shown how you add admin accounts to the chat domain classes via bootstrap in the documentation.

    Some of these things takes years to fully better understand but if I wanted to be lazy I could just copy those domain classes from the chat plugin to a test project then using grails get it to generate controllers and views for them then go back to the main project and copy across the new controllers/views.

    If a plugin provides functionality services/domain classes / controllers. Their all reusable locally in your main app. You can just expand or if its good then just contribute it back to the plugin itself for others to use