user2196112
user2196112

Reputation: 43

Play Framework 2.1 websockets in Chrome

I can't seem to get websocket communication to work in the Play Framework version 2.1.

I created a simple test that does nothing but send messages back and forth with a push of a button. All the code for it is below. But nothing shows up except for the button.

Has anybody seen this problem or can someone tell me what I may be doing wrong in the code below?

I am using the latest version of Chrome.

Here is my simple setup.

In Application.java

public static Result index() {
    return ok(index.render());
}

public static WebSocket<String> sockHandler() {
    return new WebSocket<String>() {
        // called when the websocket is established
        public void onReady(WebSocket.In<String> in,
                WebSocket.Out<String> out) {
            // register a callback for processing instream events
            in.onMessage(new Callback<String>() {
                public void invoke(String event) {
                    System.out.println(event);
                }
            });

            // write out a greeting
            out.write("I'm contacting you regarding your recent websocket.");
        }
    };
}

In Routes File GET / controllers.Application.index()

# Map static resources from the /public folder to the /assets URL path
GET     /assets/*file               controllers.Assets.at(path="/public", file)
GET     /greeter                    controllers.Application.sockHandler()

In Index.Scala.html

@main(null) {

<div class="greeting"></div>
<button class="send">Send</button>

<script type="text/javascript" charset="utf-8">

    $(function() {
        var WS = window['MozWebSocket'] ? MozWebSocket : WebSocket
        var sock = new WS("@routes.Application.sockHandler()")

        sock.onmessage = function(event) {
            $('.greeting').append(event.data)
        }

        $('button.send').click(function() {
            sock.send("I'm sending a message now.")
        });            
    })

</script>

}

In Main.scala.html

@(title: String)(content: Html)
<!DOCTYPE html>
<html>
<head>
    <title>@title</title>
    <link rel="stylesheet" media="screen" href="@routes.Assets.at("stylesheets/main.css")">
    <link rel="shortcut icon" type="image/png" href="@routes.Assets.at("images/favicon.png")">
    <script src="@routes.Assets.at("javascripts/jquery-1.7.1.min.js")" type="text/javascript"></script>
</head>
<body>
    @content
</body>

Upvotes: 0

Views: 2149

Answers (2)

Travis Kaufman
Travis Kaufman

Reputation: 2937

you can use a Route's webSocketURL() method to retrieve a url that can be passed to a WebSocket's constructor. Here's an example from Play's websocket-chat sample code:

$(function() {            
  var WS = window['MozWebSocket'] ? MozWebSocket : WebSocket
  var chatSocket = new WS("@routes.Application.chat(username).webSocketURL()")

  var sendMessage = function() {
    chatSocket.send(JSON.stringify(
      {text: $("#talk").val()}
    ))
    $("#talk").val('')
  }

  // ...

So in your code you can use something like

var sock = new WS("@routes.Application.sockHandler().webSocketURL()");

Personally I don't like intermingling interpolated code with JS, since I think that any code executing on the client should only be concerned with the state of the client, and not the server (not to mention it makes refactoring the script out into an external file impossible), so I tend to do something like this:

<div class="container app-container" 
     data-ws-uri="@routes.Application.WSUri.webSocketURL()">
.......
</div>

Then in my JS I can just do something like

var sock = new WS(document.querySelector(".app-container").dataset.wsUri);
// ....

Upvotes: 3

TizianoPiccardi
TizianoPiccardi

Reputation: 497

The problem is in

var sock = new WS("@routes.Application.sockHandler()")

you have to specify the protocol and the complete url in the format: ws://localhost:9000/greeter.

Check this question to do it in javascript: How to construct a WebSocket URI relative to the page URI?

Upvotes: 3

Related Questions