Search code examples
javaherokujava-websocketspark-java

heroku is not able to process web socket


Im trying to use web socket with spark and im using /chat as the end point url. Following is my code.

@ServerEndpoint("/chat")
public class Main {

  public static void main(String[] args) {
    port(Integer.valueOf(System.getenv("PORT")));
    Spark.staticFileLocation("/public");    
  }

  private static final Set<Session> sessions = Collections
          .synchronizedSet(new HashSet<Session>());

  private static final HashMap<String, String> nameSessionPair = new HashMap<String, String>();

  private JSONUtils jsonUtils = new JSONUtils();

  public static Map<String, String> getQueryMap(String query) {
      Map<String, String> map = Maps.newHashMap();
      if (query != null) {
          String[] params = query.split("&");
          for (String param : params) {
              String[] nameval = param.split("=");
              map.put(nameval[0], nameval[1]);
          }
      }
      return map;
  }

  @OnOpen
  public void onOpen(Session session) {

      System.out.println(session.getId() + " has opened a connection");

      Map<String, String> queryParams = getQueryMap(session.getQueryString());

      String name = "";

      if (queryParams.containsKey("name")) {

        name = queryParams.get("name");
          try {
              name = URLDecoder.decode(name, "UTF-8");
          } catch (UnsupportedEncodingException e) {
              e.printStackTrace();
          }

          nameSessionPair.put(session.getId(), name);
      }

      sessions.add(session);

      try {
          session.getBasicRemote().sendText(
                  jsonUtils.getClientDetailsJson(session.getId(),
                          "Your session details"));
      } catch (IOException e) {
          e.printStackTrace();
      }

      sendMessageToAll(session.getId(), name, " joined conversation!", true,
              false);

  }

  @OnMessage
  public void onMessage(String message, Session session) {

      System.out.println("Message from " + session.getId() + ": " + message);

      String msg = null;

      try {
          JSONObject jObj = new JSONObject(message);
          msg = jObj.getString("message");
      } catch (JSONException e) {
          e.printStackTrace();
      }

      sendMessageToAll(session.getId(), nameSessionPair.get(session.getId()),
              msg, false, false);
  }

  @OnClose
  public void onClose(Session session) {

      System.out.println("Session " + session.getId() + " has ended");

      String name = nameSessionPair.get(session.getId());

      sessions.remove(session);

      sendMessageToAll(session.getId(), name, " left conversation!", false,
              true);

  }

  private void sendMessageToAll(String sessionId, String name,
          String message, boolean isNewClient, boolean isExit) {

      for (Session s : sessions) {
          String json = null;

          if (isNewClient) {
              json = jsonUtils.getNewClientJson(sessionId, name, message,
                      sessions.size());

          } else if (isExit) {
              json = jsonUtils.getClientExitJson(sessionId, name, message,
                      sessions.size());
          } else {
              json = jsonUtils
                      .getSendAllMessageJson(sessionId, name, message);
          }

          try {
              System.out.println("Sending Message To: " + sessionId + ", "
                      + json);

              s.getBasicRemote().sendText(json);
          } catch (IOException e) {
              System.out.println("error in sending. " + s.getId() + ", "
                      + e.getMessage());
              e.printStackTrace();
          }
      }
  }
}

The problem is that the onOpen method is never called and when the user reaches the end point url , it throws 404 error. why is that so? I'm deploying it using heroku and i'm using socket_url as my site name and I have left the port empty in my js file.

How can I sort this out?


Solution

  • This code will not work with example from Heroku.com. It is because tomcat and jetty runners don't have support for websockets annotation (don't know the reason). You will be able to run it using embedded Jetty. Example of main method, pom for maven and procfile for heroku you can find at privateblog.info:

    web:    java $JAVA_OPTS -cp target/JettyServer-0.0.1-SNAPSHOT-jar-with-dependencies.jar info.privateblog.Proxy $PORT