Skip to main content

Broadcasting in WebSocket

Posted by swchan2 on August 13, 2013 at 12:09 PM PDT

Java API for WebSocket is a new JSR to Java EE 7. It provides a stardard Java API for creating WebSocket applications. This gives web applications the ability to push data.

In Java EE 6 samples, we added a chat room sample to illustrate how to use of Servlet 3.0 asynchronous operation. In that sample, the servlet code did the following:

  • keep track of AsyncContext in a Queue
  • create a thread to process the message
  • has code to workaround browser specific issue

In this blog, I will rewrite the sample using broadcasting API in WebSocket. Also, a "logout" feature is added to the sample.

The Java code for WebSocket server endpoint is as follow:

@ServerEndpoint(value="/chat")
public class ChatServer {
    @OnMessage
    public void chat(String chatMsg, Session session) throws IOException {
        String message = "";
        boolean isLogout = false;
        String user = getUser(chatMsg);
        if (chatMsg != null && chatMsg.length() >= 2) {
            char first = chatMsg.charAt(0);
            char second = chatMsg.charAt(1);
            if (second == ':') {
                switch(first) {
                    case 'i':
                        message = "System Message:" + user + " has joined.";
                        break;
                    case 'o':
                        isLogout = true;
                        message = "System Message:" + user + " has left.";
                        break;
                    default: // 'c'
                        message = chatMsg.substring(2);
                        break;
                }
            }
        }

        for (Session s : session.getOpenSessions()) {
            if (s.isOpen()) {
                send(s, message);
            }
        }

        if (isLogout) {
            session.close(new CloseReason(
                    CloseReason.CloseCodes.NORMAL_CLOSURE,
                    user + " leaves"));
        }
    }

    private void send(Session session, String message) {
        try {
            session.getBasicRemote().sendObject(message);
        } catch(Exception ex) {
            System.err.println("Error in sending message to " + session + ": " + ex);
        }
    }

    private String getUser(String chatMsg) {
        String user = "";
        if (chatMsg != null && chatMsg.length() > 1 && chatMsg.charAt(1) == ':') {
            String content = chatMsg.substring(2);
            int ind = content.indexOf(':');
            user = ((ind > 0) ? content.substring(0, ind) : content);
        }

        return user;
    }
}

The annotation @ServerEndpoint indicates that the class is a WebSocket server endpoint and @OnMessage indicates that the method chat will be invoked when a message arrived.
The session.getOpenSessions() returns all the open sessions for the given WebSocket at that moment. This allows us to do send messages to others. Note that when we decide to do any operations on returned open sessions, we need to check s.isOpen() as the session s may be closed after session.getOpenSessions() is called.

Note that there is no workaround for browser issue in the Java code.

With the new HTML5 JavaScript API, we simplify the corresponding JavaScript from about 2000 lines to less than 150 lines.
You can download the maven project here and run it on GlassFish 4.0.

AttachmentSize
20130813-websocket-chat.zip39.92 KB