Wie können Sie Akka verwenden, um eine Operation auf der db mit Hibernate auszuführen und den Webclient nicht zu blockieren?Play Framework 2.5.4 Asynchrone Ruhezustandsoperationen
UPDATE:
Stellt sich heraus, der Fehler durch die dao.get() Methode verursacht wurde. Ich änderte die start() -Methode, um ein tatsächliches Objekt und nicht die ID von der Datenbank zu nehmen, und jetzt bekomme ich keinen Fehler, aber nichts passiert (es bleibt auf em.merge() hängen, wie ich vorher sagte).
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:
Wenn ich versuche, so etwas wie:
@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));
}
Wo doStuff führt nur eine entityManager.merge(), erhalte ich:
[Abschluss Ausnahme: org .hibernate.SessionException: Session wird geschlossen]
oder
[CompletionException: java.lang.IllegalStateException: EntityManager geschlossen ist]
Wenn ich den Code unten um den obigen Prozess zu starten:
@Transactional
public Result mainMethod() {
List<SomeObject> allObjects= dao.getAll();
int size = allObjects.size();
for(int i = 0; i < size; i++) {
start(allObjects.get(i).getId());
}
return ok("Started");
}
Die neu erstellten Threads (Aktoren) geraten beim Versuch einer Datenbankoperation in eine Endlosschleife.
Danke!
komplette Stack-Trace:
play.api.http.HttpErrorHandlerExceptions $$ Anon $ 1: Ausführung Ausnahme [[CompletionException: org.hibernate.SessionException: Session geschlossen ist]] bei Spiel. api.http.HttpErrorHandlerExceptions $ .throwableToUsefulException (HttpErrorHandler.scala: 280) bei play.api.http.DefaultHttpErrorHandler.onServerError (HttpErrorHandler.scala: 206) bei play.api.GlobalSettings $ class.onError (GlobalSettings.scala: 160) bei play.api.DefaultGlobal $ .onError (GlobalSettings.scala : 188) bei play.api.http.GlobalSettingsHttpErrorHandler.onServerError (HttpErrorHandler.scala: 98) bei play.core.server.netty.PlayRequestHandler $$ anonfun $ 2 $$ anonfun $ $ 1.applyOrElse (PlayRequestHandler.scala gelten: 100) bei play.core.server.netty.PlayRequestHandler $$ anonfun $ 2 $$ anonfun $ gelten $ 1.applyOrElse (PlayRequestHandler.scala: 99) bei scala.concurrent.Future $$ anonfun $ recoverWith $ 1.Apply (Future.scala: 344) um scala.concurrent.Future $$ anonfun $ recover Mit $ 1.apply (Future.scala: 343) bei scala.concurrent.impl.CallbackRunnable.run (Promise.scala: 32) um spielen .api.libs.iteratee.Execution $ trampoline $ .executeScheduled (Ausführung.Scala: 109) bei play.api.libs.iteratee.Execution $ $ Trampolin .Execute (Execution.scala: 71) bei scala.concurrent.impl.CallbackRunnable.executeWithValue (Promise.scala: 40) bei scala.concurrent.impl.Promise $ DefaultPromise.tryComplete (Promise.scala: 248) bei scala.concurrent.Promise $ class.complete (Promise.scala: 55) um scala.concurrent.impl.Promise $ DefaultPromise.complete (Promise.scala: 153) bei scala.concurrent.java8.FuturesConvertersImpl $ P.accept (FutureConvertersImpl.scala: 94) bei scala.concurrent.java8.FuturesConvertersImpl $ P.accept (FutureConvertersImpl.scala: 89) bei java.util.concurrent.CompletableFuture.uniWhenComplete (CompletableFuture.java:760) bei java.util.concurrent.CompletableFuture $ UniWhenComplete.tryFire (CompletableFuture.java:736) bei java.util.concurrent.CompletableFuture.postComplete (CompletableFuture.java:474) bei java.util.concurrent.CompletableFuture $ AsyncSupply.run (CompletableFuture.java:1595) bei play.core.j.HttpExecutionContext $$ $ Anon 2.run (HttpExecutionContext.scala: 56) bei akka.dispatch.TaskInvocation.run (AbstractDispatcher.scala: 39) bei akka.dispatch.ForkJoinExecutorConfigurator $ AkkaForkJoinTask.exec (AbstractDispatcher.scala: 405) bei scal a.concurrent.forkjoin.ForkJoinTask.doExec (ForkJoinTask.java:260) bei scala.concurrent.forkjoin.ForkJoinPool $ WorkQueue.runTask (ForkJoinPool.java:1339) bei scala.concurrent.forkjoin.ForkJoinPool.runWorker (ForkJoinPool.java:1979) bei scala.concurrent.forkjoin.ForkJoinWorkerThread.run (ForkJoinWorkerThread.java:107) verursacht durch: java.util.concurrent.CompletionException: org.hibernate.SessionException: Session ist beendet! bei java.util.concurrent.CompletableFuture.encodeThrowable (CompletableFuture.java:273) bei java.util.concurrent.CompletableFuture.completeThrowable (CompletableFuture.java:280) bei java.util.concurrent.CompletableFuture $ AsyncSupply. run (CompletableFuture.java:1592) ... 7 gemeinsame Rahmen ausgelassen Verursacht von: org.hibernate.SessionException: Sitzung ist geschlossen! bei org.hibernate.internal.AbstractSessionImpl.errorIfClosed (AbstractSessionImpl.java:133) bei org.hibernate.internal.SessionImpl.setCacheMode (SessionImpl.java:1455) bei org.hibernate.jpa.spi.AbstractEntityManagerImpl. finden (AbstractEntityManagerImpl.java:1144) bei org.hibernate.jpa.spi.AbstractEntityManagerImpl.find (AbstractEntityManagerImpl.java:1068) bei daos.dao.get (dao.java:45) bei controllers.DemoController.lambda $ start $ 0 (DemoController.java:195) um java.util.concurrent.CompletableFuture $ AsyncSupply.run (CompletableFuture.java:1590) ... 7 gemeinsame Frames weggelassen
LE:
Versuchte mit:
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));
Und ich bekomme den gleichen Fehler.
Vielleicht ist es falsch, ich tue, Also meine einfachere Frage: Wie können Sie verhindern, dass ein Nicht-Web-Client Datenbankoperationen mit Play's Akka Actors blockiert? Starten Sie beispielsweise eine Aktualisierungsoperation, die einige Felder auf bestimmte Werte setzt, ohne dass der Client, der die Controlleraktion gesendet hat, auf das Ergebnis wartet (da dies für den Benutzer nicht relevant ist). – taviss