I'm using Play 2.0.1 with Java. Up to this point, I have loaded a page displaying data from a database using Promise. Here's the original Controller code:
public static Result index() {
// Generate the page
final MainPage page = new MainPage();
Promise<MainPage> promiseMainPage = Akka.future(
new Callable<MainPage>() {
public MainPage call() throws Exception {
page.generate();
return page;
}
});
return async(promiseMainPage.map(new Function<MainPage, Result>() {
@Override
public Result apply(MainPage mainPage) throws Throwable {
return ok(views.html.index.render(mainPage));
}
}));
}
This all works fine; the promised page does sent to the browser while the server does not block for the database query (executed in page.generate()
) to complete.
However, now I would like to use WebSocket to update the page with new/modified information retrieved from the DB.
So I've used the Chat example to do just that (even simplified, since I would like to use just the outgoing channel: server to client). I've added the following to the end of index.scala.html
:
<script type="text/javascript" charset="utf-8">
$(function() {
var WS = window['MozWebSocket'] ? MozWebSocket : WebSocket;
var socket = new WS("@(routes.Application.webSocket().webSocketURL(request))");
var receiveEvent = function(event) {
var data = JSON.parse(event.data);
var connectionStatus = data["connectionStatus"];
var connectionStatusHtml = '<font color="red">* Not connected</font>';
if (connectionStatus != undefined) {
connectionStatusHtml = '<font color="blue">' + connectionStatus + '</font>';
}
$('#connectionStatus').html(connectionStatusHtml);
}
socket.onmessage = receiveEvent;
})
</script>
I've updated routes
file and created a handler for webSocket()
request.
At this point, when I try to browse the page, I get the following error from play:
[error] play - Waiting for a promise, but got an error: null
java.lang.RuntimeException: null
at play.libs.F$Promise$2.apply(F.java:113) ~[play_2.9.1.jar:2.0.1]
at akka.dispatch.Future$$anonfun$map$1.liftedTree3$1(Future.scala:625) ~[akka-actor.jar:2.0.1]
at akka.dispatch.Future$$anonfun$map$1.apply(Future.scala:624) ~[akka-actor.jar:2.0.1]
at akka.dispatch.Future$$anonfun$map$1.apply(Future.scala:621) ~[akka-actor.jar:2.0.1]
at akka.dispatch.DefaultPromise.akka$dispatch$DefaultPromise$$notifyCompleted(Future.scala:943) [akka-actor.jar:2.0.1]
at akka.dispatch.DefaultPromise$$anonfun$tryComplete$1$$anonfun$apply$mcV$sp$4.apply(Future.scala:920) [akka-actor.jar:2.0.1]
This happens at return ok(views.html.index.render(mainPage));
.
Commenting out the script from HTML file solves this, but of course no WebSocket will open.
Is it possible to combine use of Promise and WebSocket in Play? Perhaps I miss used it?
Play is rock-solid and used by hundreds of thousands of Java and Scala developers every month. Play is still extremely relevant to today's application and web development and has a passionate and very capable community around it ensuring that it has many good years left.
Internally, Play Framework is asynchronous from the bottom up. Play handles every request in an asynchronous, non-blocking way. The default configuration is tuned for asynchronous controllers.
Play is a direct competitor to Spring framework and designed to develop and deploy web applications more efficiently and also provides better MVC framework. In terms of getting a web application up and running quickly, play is the best. Spring and Spring MVC cannot compete with play framework individually.
Play Framework makes it easy to build web applications with Java & Scala. Play is based on a lightweight, stateless, web-friendly architecture. Built on Akka, Play provides predictable and minimal resource consumption (CPU, memory, threads) for highly-scalable applications.
I do not believe you can use a promise with a web socket. However, you can use Akka to execute a task in the background. For example, the following code should let Akka handling the longer operation (database query) in the background:
public static WebSocket<String> webSocket() {
return new WebSocket<String>() {
public void onReady(final WebSocket.In<String> in, final WebSocket.Out<String> out) {
in.onMessage(new F.Callback<String>() {
public void invoke(String event) {
Akka.system().scheduler().scheduleOnce(
Duration.Zero(),
new Runnable() {
public void run() {
String result = foo(event);
out.write(result);
}
},
Akka.system().dispatcher()
);
}
});
//Handle in.onClose();
}
};
}
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