Play Framework – Est-il possible de combiner l’utilisation de Promise et WebSocket in Play?

J’utilise Play 2.0.1 avec Java. Jusqu’à présent, j’ai chargé une page affichant les données d’une firebase database à l’aide de Promise. Voici le code du contrôleur d’origine:

public static Result index() { // Generate the page final MainPage page = new MainPage(); Promise promiseMainPage = Akka.future( new Callable() { public MainPage call() throws Exception { page.generate(); return page; } }); return async(promiseMainPage.map(new Function() { @Override public Result apply(MainPage mainPage) throws Throwable { return ok(views.html.index.render(mainPage)); } })); } 

Tout cela fonctionne bien. la page promise est envoyée au navigateur alors que le serveur ne bloque pas la requête sur la firebase database (exécutée dans page.generate() ). Cependant, je voudrais maintenant utiliser WebSocket pour mettre à jour la page avec les informations nouvelles / modifiées extraites de la firebase database. C’est ce que j’ai utilisé comme exemple de chat (même simplifié, car j’aimerais utiliser uniquement le canal sortant: serveur à client). J’ai ajouté ce qui suit à la fin de index.scala.html :

  $(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 = '* Not connected'; if (connectionStatus != undefined) { connectionStatusHtml = '' + connectionStatus + ''; } $('#connectionStatus').html(connectionStatusHtml); } socket.onmessage = receiveEvent; })  

J’ai mis routes jour le fichier routes et créé un gestionnaire pour la webSocket() .

À ce stade, lorsque j’essaie de parcourir la page, l’erreur suivante apparaît lors de la lecture:

 [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] 

Cela se produit au return ok(views.html.index.render(mainPage)); . Commenter le script à partir d’un fichier HTML résout ce problème, mais bien entendu, WebSocket ne s’ouvrira pas.

Est-il possible de combiner l’utilisation de Promise et WebSocket in Play? Peut-être me manque-t-il?

Je ne crois pas que vous puissiez utiliser une promesse avec un socket Web. Cependant, vous pouvez utiliser Akka pour exécuter une tâche en arrière-plan. Par exemple, le code suivant devrait permettre à Akka de gérer l’opération la plus longue (requête de firebase database) en arrière-plan:

 public static WebSocket webSocket() { return new WebSocket() { public void onReady(final WebSocket.In in, final WebSocket.Out out) { in.onMessage(new F.Callback() { public void invoke(Ssortingng event) { Akka.system().scheduler().scheduleOnce( Duration.Zero(), new Runnable() { public void run() { Ssortingng result = foo(event); out.write(result); } }, Akka.system().dispatcher() ); } }); //Handle in.onClose(); } }; }