Question

I had recently implemented websocket on tomcat 7.0.50. my tomcat runs behind apache 2.4. I use Strtus 2 and Spring Security. It has stopped working.

Problem : Websocket connection is opened successfully. Javascript event handler get fires successfully. Apache logs show that request was accepted as an protocol upgrade request with 101 code Tomcat access logs also show the same code 101 for protocol upgrade

However on server side onOpen message is not fired. I tried sending the message as soon as connection is opened in javascript's event handler.. There is no error in javascript but Server side endPoint's onmessage is never called just like onOpen is never called.

Here are the changes I made after which it has stopped working:

 Windows Host file : I use dummy host name through Windows host file:
127.0.0.1    phasingapp.com
127.0.0.1    pricer.com

URL of wesocket :

old  :  ws://localhost:86/websocket/filuploadtrackerendpoint
new : ws://phasingapp.com:86/websocket/filuploadtrackerendpoint

Added virtual host config for apache :

 <Location /jkweb/websocket/>
    Require host phasingapp.com granted
</Location>    

JkMount /jkweb/* localtomcat
JkUnMount /jkweb/project/content/*  localtomcat
JkUnMount /jkweb/angle/content/*  localtomcat
JkUnMount /jkweb/index.jsp localtomcat
JkUnMount /jkweb/ localtomcat

ProxyRequests Off
ProxyPreserveHost On

ProxyPass /jkweb  !
ProxyPass /jkweb/  !
ProxyPass /jkweb/websocket/  ws://localhost:8080/jkweb/websocket/
ProxyPassReverse /jkweb/websocket/  ws://localhost:8080/jkweb/websocket/
ProxyPass /  http://localhost:8080/jkweb/
ProxyPassReverse /  http://localhost:8080/jkweb/

Struts 2 :

 changed url pattern for Struts 2 filter from ".action to " /* ". Also added exclusion   filters
 to strtus2  for webscoket urls :

<constant name="struts.action.excludePattern" value=".*websocket/.*"/>

Everything seems to be working fine as i am gettting no error anywhere in apache,tomcat,spring security and Struts2 logs.

However on server side no handlers are called?

Earlier I had faced similar problem but it was because I had put websocket-api jar in my WEB-INF/lib which was preventing websocket connection from getting opened. Now connection is opened but no handler is called after that and after some time connection is closed obviously because of timout I suppose.

Here is my ServerEndPoint class :

      package com.jkweb.websocket;

        import java.io.IOException;
        import java.util.HashMap;
        import java.util.List;
        import java.util.Map;

        import javax.websocket.EndpointConfig;
        import javax.websocket.OnMessage;
        import javax.websocket.OnOpen;
        import javax.websocket.Session;
        import javax.websocket.server.PathParam;
        import javax.websocket.server.ServerEndpoint;

        import org.slf4j.Logger;
        import org.slf4j.LoggerFactory;

        @ServerEndpoint(value="/websocket/fileuploadtracker")
       public class FileUploadTrackerEndPoint{
       private static final Logger logger = LoggerFactory
            .getLogger(FileUploadTrackerEndPoint.class);
       private static HashMap<String,Session> socketConnectionMap = new    HashMap<String,Session>();

    @OnOpen 
    public void open(Session session) {
        Map<String,List<String>> paramMap = session.getRequestParameterMap();
        List<String> uniqueTockenValues = paramMap.get("uniqueTocken");
        if(uniqueTockenValues != null && uniqueTockenValues.size() > 0){
            socketConnectionMap.put(uniqueTockenValues.get(0),session); 
        }
    }
    @OnMessage
    public void onMessage(Session session, String msg) {
        try {
            session.getBasicRemote().sendText(msg);
        } catch (IOException e) {
            logger.error(e.getMessage());
        }
    }

    public static void sendMessage(String uniqueTocken,String msg){
        try {
            Session wsSession = socketConnectionMap.get(uniqueTocken);
            wsSession.getBasicRemote().sendText(msg);
        } catch (IOException e) {
            logger.error(e.getMessage());
        }
    }
}

and my javascript code :

createFileUploadWebSocket : function(){
            var that = this;
            var uniqueTocken = $("#uniqueTocken").val(),
            wsurl =  "ws://phasingapp.com:86/jkweb/websocket/fileuploadtracker?uniqueTocken="+uniqueTocken,
            ws;
            ws = new WebSocket(wsurl);
             ws.onopen = function()
             {
                 alert("opened..") //I get this aler sothis is called
                 ws.send("test");//however this has not effect ...no error but server end point is not called
             };
             ws.onmessage = function (evt) 
             { 
                 message = evt.data;
                 if(message == "Done."){
                     alert("closing..");
                     ws.close();
                     $('#progressbar').progressbar('option','value',100);
             }
                 var currentVal = $('#progressbar').progressbar('option','value');
                 $('#progressbar').progressbar('option','value',currentVal <= 80 ?currentVal+1 : currentVal);
             };
             ws.onclose = function(evt)
             { 
                // websocket is closed.
                alert("Connection is closed..."+evt.code + ":"+evt.reason ); 
             };

             ws.onerror = function(evt){
                 alert("Connection is closed..."+evt.code + ":"+evt.reason );
             };

        },
Was it helpful?

Solution

Again with all other my websocket questions i found the answer in my conffiguration (misconfiguration) itself.

 ProxyPass /jkweb  !
 ProxyPass /jkweb/  !
 ProxyPass /jkweb/websocket/  ws://localhost:8080/jkweb/websocket/
 ProxyPassReverse /jkweb/websocket/  ws://localhost:8080/jkweb/websocket/
 ProxyPass /  http://localhost:8080/jkweb/
 ProxyPassReverse /  http://localhost:8080/jkweb/

I changed the order of proxypass directives like below:

 ProxyPass /jkweb/websocket/  ws://localhost:8080/jkweb/websocket/
 ProxyPassReverse /jkweb/websocket/  ws://localhost:8080/jkweb/websocket/
 ProxyPass /jkweb  !
 ProxyPass /jkweb/  !
 ProxyPass /  http://localhost:8080/jkweb/
 ProxyPassReverse /  http://localhost:8080/jkweb/

Putting it before the proxypass directive for websocket was causing every request starting with jkweb/ was causing it bypass the proxy.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top