java - Play Framework 2.5.4 Async Hibernate operations -
how can use akka perform operation on db using hibernate , not block web client?
update:
turns out error caused dao.get() method. changed start() method take actual object , not id database , no error, nothing happening(it gets stuck on em.merge() said).
public completionstage<result> start(someobject object) { executioncontext ec = akka.system().dispatchers().lookup("akka.actor.db-context"); return completablefuture.supplyasync(() -> dostuff(object), play.libs.concurrent.httpexecution.fromthread(ec)) .thenapply(i -> ok("got result: " + i)); }
outdated:
if try like:
@transactional public completionstage<result> start(long id) { executioncontext ec = akka.system().dispatchers().lookup("akka.actor.db-context"); return completablefuture.supplyasync(() -> dostuff(dao.get(id)), play.libs.concurrent.httpexecution.fromthread(ec)) .thenapply(i -> ok("got result: " + i)); }
where dostuff performs entitymanager.merge(), get:
[completionexception: org.hibernate.sessionexception: session closed!]
or
[completionexception: java.lang.illegalstateexception: entitymanager closed]
when use code below start process above:
@transactional public result mainmethod() { list<someobject> allobjects= dao.getall(); int size = allobjects.size(); for(int = 0; < size; i++) { start(allobjects.get(i).getid()); } return ok("started"); }
then newly created threads(actors) infinite loop when trying database operation.
thanks!
complete stack trace:
play.api.http.httperrorhandlerexceptions$$anon$1: execution exception[[completionexception: org.hibernate.sessionexception: session closed!]] @ play.api.http.httperrorhandlerexceptions$.throwabletousefulexception(httperrorhandler.scala:280) @ play.api.http.defaulthttperrorhandler.onservererror(httperrorhandler.scala:206) @ 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:100) @ play.core.server.netty.playrequesthandler$$anonfun$2$$anonfun$apply$1.applyorelse(playrequesthandler.scala:99) @ 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) @ play.api.libs.iteratee.execution$trampoline$.executescheduled(execution.scala:109) @ play.api.libs.iteratee.execution$trampoline$.execute(execution.scala:71) @ scala.concurrent.impl.callbackrunnable.executewithvalue(promise.scala:40) @ scala.concurrent.impl.promise$defaultpromise.trycomplete(promise.scala:248) @ scala.concurrent.promise$class.complete(promise.scala:55) @ scala.concurrent.impl.promise$defaultpromise.complete(promise.scala:153) @ scala.concurrent.java8.futuresconvertersimpl$p.accept(futureconvertersimpl.scala:94) @ scala.concurrent.java8.futuresconvertersimpl$p.accept(futureconvertersimpl.scala:89) @ java.util.concurrent.completablefuture.uniwhencomplete(completablefuture.java:760) @ java.util.concurrent.completablefuture$uniwhencomplete.tryfire(completablefuture.java:736) @ java.util.concurrent.completablefuture.postcomplete(completablefuture.java:474) @ java.util.concurrent.completablefuture$asyncsupply.run(completablefuture.java:1595) @ play.core.j.httpexecutioncontext$$anon$2.run(httpexecutioncontext.scala:56) @ akka.dispatch.taskinvocation.run(abstractdispatcher.scala:39) @ akka.dispatch.forkjoinexecutorconfigurator$akkaforkjointask.exec(abstractdispatcher.scala:405) @ scala.concurrent.forkjoin.forkjointask.doexec(forkjointask.java:260) @ scala.concurrent.forkjoin.forkjoinpool$workqueue.runtask(forkjoinpool.java:1339) @ scala.concurrent.forkjoin.forkjoinpool.runworker(forkjoinpool.java:1979) @ scala.concurrent.forkjoin.forkjoinworkerthread.run(forkjoinworkerthread.java:107) caused by: java.util.concurrent.completionexception: org.hibernate.sessionexception: session closed! @ 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) ... 7 common frames omitted caused by: org.hibernate.sessionexception: session closed! @ org.hibernate.internal.abstractsessionimpl.errorifclosed(abstractsessionimpl.java:133) @ org.hibernate.internal.sessionimpl.setcachemode(sessionimpl.java:1455) @ org.hibernate.jpa.spi.abstractentitymanagerimpl.find(abstractentitymanagerimpl.java:1144) @ org.hibernate.jpa.spi.abstractentitymanagerimpl.find(abstractentitymanagerimpl.java:1068) @ daos.dao.get(dao.java:45) @ controllers.democontroller.lambda$start$0(democontroller.java:195) @ java.util.concurrent.completablefuture$asyncsupply.run(completablefuture.java:1590) ... 7 common frames omitted
le:
tried with:
executioncontext ec = akka.system().dispatchers().lookup("akka.actor.db-context"); return completablefuture.supplyasync(() -> jpa.withtransaction("default", true, ()-> dostuff(dao.get(id))), play.libs.concurrent.httpexecution.fromthread(ec)) .thenapply(i -> ok("got result: " + i));
and same error.
the @transactional annotation on synchronous method. guess need transaction inside async block. can use jpa method withtransaction instead of annotation. signature (from play java api)
/** * run block of code in jpa transaction. * * @param name persistence unit name * @param readonly transaction read-only? * @param block block of code execute * @param <t> type of result * @return code execution result */ public <t> t withtransaction(string name, boolean readonly, supplier<t> block);
it should this:
inject jpaapi in controller:
@inject jpaapi jpa;
implement async executor call jpa:
jpa.withtransaction("default", true, ()->dostuff(dao.get(id)), play.libs.concurrent.httpexecution.fromthread(ec)) .thenapply(i -> ok("got result: " + i)));
note second argument true in call withtransaction readonly operation (in case).
- change dao class use injected jpaapi well.
Comments
Post a Comment