I am trying to implement a WebSockets based solution with Play2 and Java. Currently I'm not using Actor Model for concurrency management. Instead, it's just handling the WebSockets using callbacks.
The problem is the server is unable to 'broadcast' the messages across to multiple clients. For example, I need all the active browser sessions to receive a simple notification after an action is triggered through a client. Instead, I'm just able to simulate this for a single client session. In effect, it just acts as a regular Ajax request/response scenario.
My guess is the WebSockets solution with Play2 & Java with simple callbacks isn't able to broadcast the messages to all of the connected client browsers.
Callback server code
public static WebSocket<String> heartUpdate() {
return new WebSocket<String>() {
public void onReady(final WebSocket.In<String> in,
WebSocket.Out<String> out) {
in.onMessage(new Callback<String>() {
@Override
public void invoke(String event) throws Throwable {
Product product = Product.find.byId(Long.decode(event));
// Other business stuff
out.write(entity.id + " " + decimalValue);
}
});
in.onClose(new Callback0() {
@Override
public void invoke() throws Throwable {
}
});
out.write(DELIM_USERID_REP);
}
};
}
Routes entry
GET /repsocket controllers.Application.heartUpdate
Client side
<script>
// Onto the WebSockets now
var WS = window['MozWebSocket'] ? MozWebSocket : WebSocket;
var socket = new WS("@routes.Application.heartUpdate.webSocketURL(request)");
var receiveEvent = function(event) {
alert(event.data);
// Notification badge visible with a common text
$('#notify').text(event.data);
$('#notify').addClass('visible');
}
$('#heart').click(function(e) {
e.preventDefault();
socket.send(@product.id);
});
socket.onmessage = receiveEvent;
</script>
In the above case, the action triggering client is the one that successfully receives the message from the server, while any other browser sessions do not.
I failed to find any documentation aligned with Play2 with Java & WebSockets that suggests a mandatory use of Actors to maintain a consistent communication with all connected active clients.
Question: Should WebSockets in Play2 with Java be implemented with Actor Model to broadcast the message to all active client sessions?
Edit: The screenshot below reflects the 2 states of browsers to which I have logged in to using 2 valid user credentials.
Ideally, WebSockets' response from the server should create the same notification badges on both the browsers.
Looking at the code you posted, it seems the problem is that you are not saving a reference to each connection, so you can later broadcast messages. Something like this:
// Just an example: does not deal with concurrency problems
private static final Set<WebSocket.Out<String>> SOCKETS = new HashSet<>();
public static WebSocket<String> heartUpdate() {
return new WebSocket<String>() {
public void onReady(final WebSocket.In<String> in,
final WebSocket.Out<String> out) {
SOCKETS.add(out);
in.onMessage(new Callback<String>() {
@Override
public void invoke(String event) throws Throwable {
for(WebSocket.Out<String> s: SOCKETS) {
s.write("SOME MESSAGE");
}
}
});
in.onClose(new Callback0() {
@Override
public void invoke() throws Throwable {
SOCKETS.remove(out);
}
});
}
};
}
You can also use actors to model this problem: having an actor responsible to keep track of the connections and to deal with new sockets connection/close.
If you want to use Akka there are some activator templates to get you started.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With