Tips for implementing WebSockets with Play Framework

I recently downloaded Play Framework from GitHub and successfully compiled it. My goal now is to implement WebSockets using a JavaScript client along with a WebSocket controller similar to the one outlined in the Using WebSockets documentation. However, despite being able to establish a WebSocket connection, the controller does not receive any messages that I send to it. Additionally, I encountered an issue where I am unable to close the WebSocket using ws.close();. Strangely enough, refreshing my webpage in the browser results in the WebSocket closing on the server side.

How can I effectively send and receive WebSocket messages using Play Framework?

Below is the code snippet of my Play Framework WebSocketController:

public class TestSocket extends WebSocketController {

    public static void hello(String name) {

        while(inbound.isOpen()) {
            WebSocketEvent evt = await(inbound.nextEvent());
            if(evt instanceof WebSocketFrame) {
                WebSocketFrame frame = (WebSocketFrame)evt;
                System.out.println("received: " + frame.getTextData());
                if(!frame.isBinary()) {
                    if(frame.getTextData().equals("quit")) {
                        outbound.send("Bye!");
                        disconnect();
                    } else {
                        outbound.send("Echo: %s", frame.getTextData());
                    }
                }
            } else if(evt instanceof WebSocketClose) {
                System.out.println("socket closed");
            }
        }
    }

}

And here is a peek at my JavaScript client implementation:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>WebSocket test</title>
<style>
.message {background: lightgray;}
</style>
<script>
window.onload = function() {
    document.getElementById('sendbutton')
        .addEventListener('click', sendMessage, false);
    document.getElementById('connectbutton')
        .addEventListener('click', connect, false);
    document.getElementById('disconnectbutton')
        .addEventListener('click', disconnect, false);
}

function writeStatus(message) {
    var html = document.createElement("div");
    html.setAttribute('class', 'message');
    html.innerHTML = message;
    document.getElementById("status").appendChild(html);
}

function connect() {
    ws = new WebSocket("ws://localhost:9000/ws?name=TestUser");

    ws.onopen = function(evt) { 
        writeStatus("connected");
    }

    ws.onclose = function(evt) {
        writeStatus("disconnected");
    }

    ws.onmessage = function(evt) {
        writeStatus("response: " + evt.data);
    }

    ws.onerror = function(evt) {
        writeStatus("error: " + evt.data);
    }
}

function disconnect() {
    ws.close();
}

function sendMessage() {
    ws.send(document.getElementById('messagefield').value);
}
</script>
</head>
<body>
<h1>WebSocket test</h1>
<button id="connectbutton">Connect</button>
<button id="disconnectbutton">Disconnect</button><br>
<input type="text" id="messagefield"/><button id="sendbutton">Send</button>
<div id="status"></div>
</body>
</html>

Answer №1

After testing your code on Chrome 14 and 15, as well as Firefox 7 using the latest version of Play from the Master Branch, I found that it mostly works. I was able to

  • establish a connection
  • send messages

To make it function properly, I made the following changes:

  • Declared ws at a global scope by adding var ws = null just before the window.onload function.
  • In Firefox, I had to use MozWebSocket instead of WebSocket, so I included an if statement to check for the browser type.
  • Modified frame.getTextData() to frame.textData
  • Changed frame.isBinary() to frame.isBinary

The last two adjustments were necessary in order to compile the code successfully?

Answer №2

The code mentioned was causing issues on my browser Chrome 20 and Play 1.2.4

After updating to Play 1.2.5, the problem disappeared completely!

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Invoking a Node.js function using a URL reference

Is there a way to call a function located in a remote URL? I have the page URL and the function name. The server-side application is running on NodeJs Express, and the function structure is as follows: function executer(param1, param2){ //logic re ...

Java applet 'disguises' Facebook pop-ups

While deploying an applet, the issue arises where almost every Facebook popup dialog is obstructed by the applet. The webpage is coded in PHP and the applet is embedded using the applet tag. This problem persists even when using JNLP starter. This error h ...

Completing the pledge using ionic/ui-routing

I've encountered an issue with my promise not resolving as expected while using Ionic/ui-routing. This is the structure of my service: return { all: function () { $localForage.getItem('foo').then(function (bar) { re ...

Adding multiple images from URLs to a ListView in a Java Android app is a common task that

When I look at my app, I notice that the list view with uploaded videos is being populated from JSON data. The JSON response also includes the URL to the video image. However, when I try to display this image in an ImageView within my XML layout for the Li ...

Avoid wrapping elements

Is there a foolproof method or best practice to prevent an HTMLElement from wrapping? Specifically, I'm referring to elements with relative positioning. One possible solution could be using absolute elements and adjusting their left position based on ...

How do I utilize ng-repeat in Angular to pass a variable that specifies the number of repetitions?

When working on my app, I encountered a situation where I needed to retrieve elements from a database and display them using ng-reat. Everything was going smoothly until I realized that within this list, there was another set of data that required a separa ...

Trouble arises when attempting to establish an isolated scope within Angular alongside UI Bootstrap

My table of data is set up with AngularJS, and one of the columns is calculated using a function in the controller. On my webpage, I have a button that opens a modal. When I use UI Bootstrap to open the modal, it creates a new isolated scope (child of the ...

When two classes contain instances of one another, it can result in a stack overflow error

In the context of two classes, Calculator and MenubarListener, there is a challenge with accessing methods from one class within another. The Calculator class contains an instance of MenubarListener, and in the MenubarListener class, there is a need to acc ...

Tips for validating boolean values in Selenium WebDriver

I am trying to verify a boolean flag called "worklogMatch" to be true. If it is not true, I want to output an error message. Below is the code snippet I am using: List<WebElement> worklogObj = driver().findElements(By.xpath("//div[@class='ng-sc ...

sending data from a callback to an express router

As I embark on learning node.js, I've encountered a challenging issue. In my passportAuth.js file, I create a user and have a callback to ensure the user is created successfully. The code snippet looks something like this: req.tmpPassport = {}; var ...

What is the best way to display multiple files in a vertical stack when choosing a file?

<div class="selected-file-container align-items-center justify-content-between d-none"> <div class="selected-file d-flex align-items-center"> <img id="selectedImage" class="hidden" src="&qu ...

Implementing custom CSS styles for HighCharts API pie chart drilldown labels

I successfully created a pie chart using highcharts and configured the chart with the following options: chart: { type: 'pie', }, In order to change the width of the text on the chart, I added the following options which force e ...

What sets @vue/cli-plugin-unit-jest apart from vue-jest?

Can you explain the distinction between these two software bundles? @angular/cli-plugin-unit-jasmine angular-jasmin If I already have one, is there a need for the other? And in what circumstances should each be utilized? ...

Is it possible that .focus() does not function on a duplicated object?

Greetings to all! I have created a form with rows of input text fields. Users can add as many rows as needed by clicking the 'add row' button. The functionality to clone() for adding rows is working perfectly. In each row, an input field can o ...

Is there a way to access various history.pushState events when using window.popState in JavaScript?

In my code, there are two pushStates that I need to read separately and execute different functions for. However, when the form is not submitted, the related pushState does not trigger and results in this error: Uncaught TypeError: Cannot read property &ap ...

The picture is displayed just once, despite the fact that it was supposed to be returned 50 times within the loop

I'm encountering an issue while trying to use a for loop to render an image in a React component. The loop is not functioning as expected, resulting in the image being displayed only once on the screen even though the intention is to show the same ima ...

Relative paths in Selenium using Java

One of my files is designated for uploading private String myPath = "..server\\app\\src\\test\\resources"; This file is stored in source control, with everyone having the same structure after the server directory. ...

Add a new division to a component when a specific event handler is triggered by another component using React and the reduce method

Currently, I am developing an interactive drag-and-drop application using React and Redux. My goal is to insert a new div element into a container when the ondragstart event handler is triggered by a component. The component responsible for the dragging o ...

Expanding div width with jQuery as a percentage

Currently, I am facing a dilemma as I try to devise an equation for expanding the width of a div based on its current height. The Scenario Within this situation, there is a div that features a background image set to "contain." The original background ima ...

Hide an absolutely positioned div when another element is clicked outside of it

Here is the code for the function that executes when a button on my website is clicked: function displayOverlay() { document.getElementById("overlay").style.visibility = "visible"; document.getElementById("dim").style.visibility = "visible"; d ...