Ausgabe
Meine Datenbankmethoden geben eine CompletableFuture zurück, um die Arbeit mit der Datenbank asynchron zu erledigen und dann das Ergebnis im Hauptthread zu verarbeiten.
public interface IAccountDAO {
CompletableFuture<ObjectId> create(AccountEntity accountEntity);
CompletableFuture<Optional<AccountEntity>> get(String nickname);
CompletableFuture<Void> update(AccountEntity accountEntity);
CompletableFuture<Void> delete(AccountEntity accountEntity);
}
Jede der Methoden enthält den folgenden Code (Beispiel einer get(String)
Methode):
@Override
public CompletableFuture<Optional<AccountEntity>> get(String nickname) {
return CompletableFuture.supplyAsync(() -> {
try {
// something logic
return Optional.of(...);
} catch (SomethingException ex) {
ex.printStackTrace();
throw new CompletionException(ex);
}
});
}
Umgang mit dem Ergebnis:
CompletableFuture<Optional<AccountEntity>> cf = get("Test_Nickname");
// Notify end user about exception during process
cf.exceptionally(ex -> {
System.out.println("Database operation failed. Stacktrace:");
ex.printStackTrace();
return Optional.ofEmpty(); // I must return something fallback value that passes to downstream tasks.
});
// Downstream tasks that I would to cancel if exception fired
cf.thenAccept(...);
cf.thenRun(...);
cf.thenRun(...);
Daher kann die Operation mit der Datenbank eine Ausnahme auslösen. In diesem Fall würde ich eine Ausnahme übergeben und .exceptionally(...)
den Benutzer benachrichtigen, der diese Methode aufgerufen hat, und die Ausführung der Kette STOPPEN (nachgelagerte Aufgaben abbrechen).
Meine Frage ist: Wie kann ich nachgelagerte Aufgaben abbrechen, wenn CompletableFuture mit Ausnahme abgeschlossen ist?
Lösung
Ich glaube nicht, dass Sie die nachgelagerten Aufgaben abbrechen können.
Alles, was Sie tun können, ist, die nachgelagerten Aufgaben im Falle einer Ausnahme einfach nicht auszuführen.
CompletableFuture<Optional<AccountEntity>> cf = get("Test_Nickname");
cf.whenComplete((response, exception) -> {
if (exception == null) {
// Downstream tasks that I would to like to run on this response
} else {
//Notify end user of the exception
}
});
Um Verschachtelungen zu vermeiden.
private Response transformResponse(GetResponse r) {
try {
return SuccessResponse();
} catch (Exception e) {
return FailedResponse();
}
}
get("Test_Nickname")
.thenApply(r -> transformResponse(r))
.thenCompose(... //update)
Beantwortet von – Ankit Sharma
Antwort geprüft von – Katrina (FixError Volunteer)