2017-11-21 3 views
0

Ich schrieb eine Play-Framework-Webanwendung und ich habe das folgende Problem. Ich habe einige DAOs, die auf die Datenbank zugreifen, und manchmal hängt eine Anfrage an die Datenbank von Informationen einer anderen Anfrage ab.Execute CompletableFuture, die von einer anderen Aufgabe abhängt

Hier ist eines der Probleme: Ich führe die getLicenseByKey Methode asynchron aus und bekomme das Ergebnis. Jetzt kann ich version_dao.getVersionUntilX() mit dem Ergebnis der license_dao Anfrage ausführen. Das Problem hierbei ist, dass die .get()-Funktion von CompletableFuture auf dem HttpExecutionContext (Blockieren eines der HTTP-Threads von Akka (Play Framework)) ausgeführt wird, und wenn diese Datenbankanforderung lange dauert, wird der Thread blockiert. Wie kann ich die license_dao.getLicenseByKey() asynchron ausführen und dann mit dem Ergebnis dieser Methode die version_dao.getVersionUntilX() Methode auch asynchron ausführen? Und wenn beide fertig sind, möchte ich das HTTP-Ergebnis von HttpExecutionContext von Play zurückgeben.

public CompletionStage<Result> showDownloadScreen(String license_key) { 
    return license_dao.getLicenseByKey(license_key).thenApplyAsync(license -> { 
     try { 
      if(license!=null) { 

       if(license.isRegistered()) { 
        return ok(views.html.download.render(license, 
         version_dao.getVersionUntilX(license.getUpdates_until()) 
         .toCompletableFuture().get())); 
       }else { 
        return redirect(routes.LicenseActivationController.showActivationScreen(license_key)); 
       } 
      }else { 
       return redirect(routes.IndexController.index("Insert Key can not be found!")); 
      } 
     } catch (InterruptedException | ExecutionException e) { 
      return redirect(routes.IndexController.index("Error while checking the Verison")); 
     } 
    }, httpExecutionContext.current()); 
} 

Antwort

0

Verwenden thenComposeAsync() statt thenApplyAsync(), und lassen Sie Ihre innere Lambda Rückkehr auch eine CompletableFuture:

public CompletionStage<Result> showDownloadScreen(String license_key) { 
    return license_dao.getLicenseByKey(license_key).thenComposeAsync(license -> { 
     try { 
      if(license!=null) { 
       if(license.isRegistered()) { 
        return version_dao.getVersionUntilX(license.getUpdates_until()) 
         .toCompletableFuture() 
         .thenApply(v -> ok(views.html.download.render(license, v))); 
       } else { 
        return CompletableFuture.completedFuture(redirect(routes.LicenseActivationController.showActivationScreen(license_key))); 
       } 
      } else { 
       return CompletableFuture.completedFuture(redirect(routes.IndexController.index("Insert Key can not be found!"))); 
      } 
     } catch (InterruptedException | ExecutionException e) { 
      return CompletableFuture.completedFuture(redirect(routes.IndexController.index("Error while checking the Verison"))); 
     } 
    }, httpExecutionContext.current()); 
} 

Da das Lambda recht komplex ist, wäre es auch wert sein, es zu einem separaten Verfahren zu extrahieren, und mach etwas mehr aufräumen.

Verwandte Themen