java - Play Framework 2.5 JavaAsync throwing CompletionException -


i'm using play 2.5 build simple app. better performance i'm using akka chunked response java 8 completionstage strategy. below code chunked response getting generated(it's working fine when not using comperablefuture):

@singleton public class abstractsource {      public source<bytestring, ?> getchunked(string html) {          return source.<bytestring>actorref(256, overflowstrategy.dropnew())                 .mapmaterializedvalue(sourceactor -> {                     sourceactor.tell(bytestring.fromstring(html), null);                     sourceactor.tell(new status.success(notused.getinstance()), null);                     return null;                 });      }  } 

and here controller:

@singleton @addcsrftoken public class application extends controller {      @inject     private abstractsource abstractsource;      public completionstage<result> index() {           completionstage<source<bytestring, ?>> source = completablefuture.supplyasync(() ->                                                    abstractsource.getchunked(index.render(csrf.gettoken(request()).map(t ->                                                      t.value()).orelse("no token")).body()                                                    )                                                 );          return source.thenapply( chunks -> ok().chunked(chunks));      }  } 

now when i'm running app it's throwing following exception:

play.api.http.httperrorhandlerexceptions$$anon$1: execution exception[[completionexception: java.lang.runtimeexception: there no http context available here.]]     @ play.api.http.httperrorhandlerexceptions$.throwabletousefulexception(httperrorhandler.scala:269)     @ play.api.http.defaulthttperrorhandler.onservererror(httperrorhandler.scala:195)     @ play.api.globalsettings$class.onerror(globalsettings.scala:160)     @ play.api.defaultglobal$.onerror(globalsettings.scala:188)     @ play.api.http.globalsettingshttperrorhandler.onservererror(httperrorhandler.scala:98)     @ play.core.server.netty.playrequesthandler$$anonfun$2$$anonfun$apply$1.applyorelse(playrequesthandler.scala:99)     @ play.core.server.netty.playrequesthandler$$anonfun$2$$anonfun$apply$1.applyorelse(playrequesthandler.scala:98)     @ scala.concurrent.future$$anonfun$recoverwith$1.apply(future.scala:344)     @ scala.concurrent.future$$anonfun$recoverwith$1.apply(future.scala:343)     @ scala.concurrent.impl.callbackrunnable.run(promise.scala:32) caused by: java.util.concurrent.completionexception: java.lang.runtimeexception: there no http context available here.     @ java.util.concurrent.completablefuture.encodethrowable(completablefuture.java:273)     @ java.util.concurrent.completablefuture.completethrowable(completablefuture.java:280)     @ java.util.concurrent.completablefuture$asyncsupply.run(completablefuture.java:1592)     @ java.util.concurrent.completablefuture$asyncsupply.exec(completablefuture.java:1582)     @ java.util.concurrent.forkjointask.doexec(forkjointask.java:289)     @ java.util.concurrent.forkjoinpool$workqueue.runtask(forkjoinpool.java:1056)     @ java.util.concurrent.forkjoinpool.runworker(forkjoinpool.java:1692)     @ java.util.concurrent.forkjoinworkerthread.run(forkjoinworkerthread.java:157) caused by: java.lang.runtimeexception: there no http context available here.     @ play.mvc.http$context.current(http.java:57)     @ play.mvc.controller.request(controller.java:36)     @ com.mabsisa.ui.web.controllers.application.lambda$index$1(application.java:31)     @ java.util.concurrent.completablefuture$asyncsupply.run(completablefuture.java:1590)     ... 5 common frames omitted 

i'm not using http context anywhere, why not working i'm not getting. same code working when returning normal result chunked response. please this

you have to supply http execution context when dealing completablefuture / completionstage. in scala context information passed via implicits, these not available in java - why play uses threadlocal.

however can lose information when switching threads , why have problem. may think don't access http context - using request().

so have change code use supplyasync executor:

https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/completablefuture.html#supplyasync-java.util.function.supplier-java.util.concurrent.executor-

from this:

completablefuture.supplyasync(() -> abstractsource.getchunked(index.render(csrf.gettoken(request()).map(t ->                                                      t.value()).orelse("no token")).body()                                                    )                                                 ); 

to this:

completablefuture.supplyasync(() -> abstractsource.getchunked(index.render(csrf.gettoken(request()).map(t ->                                                      t.value()).orelse("no token")).body()                                                    )                                                 , ec.current()); 

where ec context: @inject httpexecutioncontext ec;


Comments