3

I'm trying to implement WebSocket on my site. Following basic tutorials I added this class:

@ServerEndpoint(value="/websocketendpoint")
public class WebSocket {
    private static Set<Session> peers = Collections.synchronizedSet(new HashSet<Session>());

    @OnMessage
    public String onMessage(String message){ return null; }

    @OnOpen
    public void onOpen(Session peer){ peers.add(peer); }

    @OnClose
    public void onClose(Session peer){ peers.remove(peer); }
}

And this JS:

var wsUri = "ws://" + document.location.host + document.location.pathname + "websocketendpoint";
var ws = new WebSocket(wsUri);
ws.onopen = function(){
    ws.send("Message to send");
    alert("Message is sent...");
};
ws.onmessage = function (evt){   
    var received_msg = evt.data;
    alert("Message is received...");
};
ws.onclose = function(){ 
    alert("Connection is closed...");
};

I added the js to one of my pages, and only ws.onclose is called, in console I get this error:

Firefox: Firefox can't establish a connection to the server at ws://localhost:8080/Mysite/websocketendpoint

Chrome: Error during WebSocket handshake: Unexpected response code: 404

I tried using 'ws://echo.websocket.org' as wsUri and it works, so I guess the problem is on server side.

I'm using the following libraries: javaee-api-7.0, javax.websocket-api-1.0 My browsers are compatible with websockets (I checked)

Similar topics didn't help me, so I'm asking you for sugestions on how to fix the problem

Alexandru Severin
  • 6,021
  • 11
  • 48
  • 71
  • Where does `Mysite` come from? Is the WAR file deployed under this name? Is there any other path element that the server is using for the WS endpoint? –  Jul 16 '14 at 12:19
  • @Tichodroma `Mysite` is the name of my project in tomcat, I'm not sure what you mean in the second question. – Alexandru Severin Jul 16 '14 at 12:45

4 Answers4

9

You might want to check if this is the root of your error: tomcat 7.0.50 java webscoket implementation gives 404 error

Tomcat has a JSR-356 (i.e. the websocket API) implementation since version 7.0.47. It provides also the javax.websocket-api-1.0.jar library so this is not needed in you application. You might need it at compile time but the server will provide it at runtime (that's what provided scope means in maven if you are not familiar with the tool)

Make sure javax.websocket-api-1.0.jar does not get deployed in your WAR, do a right click in your Eclipse server view, Clean... followed by Clean Tomcat work directory... then a Publish and try again.

Community
  • 1
  • 1
Bogdan
  • 23,890
  • 3
  • 69
  • 61
  • You are right. Sorry for duplicate, I ran across that topic myself and read it twice but didn't understand it. Your answer is much easier for a beginner to understand. – Alexandru Severin Jul 17 '14 at 08:19
  • 1
    I have the same problem, and the fix mentioned above didn't fix it. It's strange because it works on my local machine, but not when I deploy it to a centos7 server. Only difference between the two set ups is my local machine uses tomcat 8.0.23 and the server uses 8.0.36, any help would be greatly appreciated – kujosHeist Sep 05 '16 at 23:36
1

I ran into this same issue and solved it by using tomcat7-websocket.jar instead of javax.websocket-api.jar. Use this dependency:

<dependency org="org.apache.tomcat" name="tomcat7-websocket" rev="7.0.52"/>

or place the tomcat7-websocket.jar in /usr/share/tomcat7/lib/

Jim
  • 11
  • 1
0

I ran into the same set of symptoms, that had a different cause, which people landing on this question might want to be aware of. Everything worked great locally but failed 404 in tomcat and the same error messages as this question when the server was deployed in AWS. The problem turned out to be that in AWS my web socket was being passed through an Apache httpd front end via ProxyPass directives.

<Location "/myApp">    
    AuthType Basic
    AuthName "Authorized Users Only"
    AuthBasicProvider file
    AuthUserFile "/usr/local/secure/htpasswd/passwords"
    Require user my_user
    ProxyPass http://localhost:8080/myApp
    ProxyPassReverse http://localhost:8080/myApp
</Location>

However, this caused the request to be turned into an http:// request not a ws:// request when it was passed on to tomcat.

The solution was to write a more specific Location that covers the websocket only.

<Location "/myApp/socket">    
    AuthType Basic
    AuthName "Authorized Users Only"
    AuthBasicProvider file
    AuthUserFile "/usr/local/secure/htpasswd/passwords"
    Require user my_user
    ProxyPass ws://localhost:8080/myApp/socket
    ProxyPassReverse ws://localhost:8080/myApp/socket
</Location>
Gus
  • 6,719
  • 6
  • 37
  • 58
0

I suffered from this problem for days.

I was using tomcat7. I tried adding jars to jvm, but no point.

Finally, I upgraded to tomcat8.5 link here and worked like charm!