Monday, October 16, 2017

Grails 2.4 Traditional WebSocket Example | Grails Chat Application | Traditional Web Socket Chat Example

Grails 2.4 Traditional WebSocket Example | Grails Chat Application | Traditional Web Socket Chat Example

At first you need to create a configurator class under src/groovy as below:


import javax.websocket.HandshakeResponse
import javax.websocket.server.HandshakeRequest
import javax.websocket.server.ServerEndpointConfig
/**
 * Created by pritom on 5/10/2017.
 */
class TraditionalWebSocketConfigurator extends ServerEndpointConfig.Configurator {
    @Override
    public void modifyHandshake(ServerEndpointConfig config, HandshakeRequest request, HandshakeResponse response) {
        config.userProperties.put("MyKey", 100)
        config.userProperties.put("session", request.httpSession)
    }
}

Next you have to create a Handler class under scr/groovy as below:


import org.springframework.scheduling.TaskScheduler
import org.springframework.scheduling.concurrent.ConcurrentTaskScheduler

import javax.servlet.ServletContext
import javax.servlet.annotation.WebListener
import javax.websocket.*
import javax.websocket.server.ServerContainer
import javax.websocket.server.ServerEndpoint
/**
 * Created by pritom on 5/10/2017.
 */
@WebListener
@ServerEndpoint(value = "/WebSocket/traditional", configurator = TraditionalWebSocketConfigurator.class)
class TraditionalWebSocketHandler {
    private static List<Session> clients = []
    private static TaskScheduler clientRemoveScheduler = new ConcurrentTaskScheduler()

    @OnOpen
    public void handleOpen(Session userSession, EndpointConfig endpointConfig) {
        clients.add(userSession)
        println "WE HAVE OPEN SESSION #${userSession.id} " +
                "SESSION ${userSession.userProperties.session.id}"
    }

    @OnMessage
    public void handleMessage(String message, Session userSession) throws IOException {
        if (message) {
            println("SENDING TO ${clients.findAll { it.isOpen() }.size()}/${clients.size()} CLIENTS")
            message = "${userSession.id}: ${message}".toString()
            clients.findAll { it.isOpen() }.each { it.basicRemote.sendText(message) }
        }
    }

    @OnClose
    public void handeClose(Session userSession) throws SocketException {
        println "ONE CONNECTION CLOSED"
    }

    @OnError
    public void handleError(Throwable throwable) {
        println("HANDLE ERROR")
        throwable.printStackTrace()
    }

    static void init(final ServletContext servletContext) {
        final ServerContainer serverContainer = servletContext.getAttribute("javax.websocket.server.ServerContainer")
        serverContainer.addEndpoint(TraditionalWebSocketHandler)
        serverContainer.defaultMaxSessionIdleTimeout = 0

        clientRemoveScheduler.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                try {
                    clients.removeAll { !it.isOpen() }
                }
                catch (Exception ex) {

                }
            }
        }, 1000L * 10)
    }
}

Next step is to init Handler from BootStrap.groovy as below:


import com.socket.TraditionalWebSocketHandler
import org.codehaus.groovy.grails.commons.GrailsApplication

import javax.servlet.ServletContext

class BootStrap {
    ServletContext servletContext
    GrailsApplication grailsApplication

    def init = { servletContext ->
        TraditionalWebSocketHandler.init(servletContext)
    }

    def destroy = {

    }
}

You are already done, next step is to generate a view to show chat window:


class SocketController {
    def index() {
        session.name = "Pritom Kumar"
        render view: "index"
    }
}


<html>
<head>
    <asset:javascript src="jquery-2.1.3.js"/>
</head>

<body>

<table>
    <tr>
        <td>User Message</td>
        <td><input type="text" autofocus class="message" required/></td>
    </tr>
    <tr>
        <td></td>
        <td><input class="button" type="button" value="Send"/></td>
    </tr>
</table>

<div class="log_div"></div>

<script type="text/javascript">
    var socket = new WebSocket("ws://localhost:8807/socket-chat-application/WebSocket/traditional");
    socket.onopen = function () {
        socket.send('Hello');
    };
    socket.onmessage = function (message) {
        $(".log_div").prepend("<div>" + message.data + "</div>");
    };
    socket.onclose = function () {

    };
    socket.onerror = function () {

    };

    $(".button").click(function () {
        var value = $.trim($(".message").val());
        if (value.length > 0) {
            socket.send(value);
            $(".message").val("").focus();
        }
    });

    $(".message").keypress(function (e) {
        if (e.keyCode == 13) {
            $(".button").click();
        }
    });
</script>

</body>
</html>

And finally below is a screenshot of browser interaction:



1 comment: