Ausgabe
Ich versuche, ein Projekt für die Verwendung von Spring WebFlux zu konvertieren, und habe ein Problem damit, einige grundlegende Geschäftslogiken zum Laufen zu bringen. Ich habe eine Repository-Schicht, die für das Abrufen / Beibehalten von Datensätzen verantwortlich ist, und eine Dienstschicht, die für die Geschäftsregeln der Anwendung verantwortlich ist. Was ich (in der Dienstebene) tun möchte, ist zu prüfen, ob für den angegebenen Benutzernamen bereits ein Benutzer vorhanden ist. Wenn ja, möchte ich mit einem Fehler antworten. Wenn nicht, möchte ich die Einfügung zulassen.
Ich rufe eine Methode auf der Repository-Ebene auf, die einen Benutzer anhand des Benutzernamens findet, und wenn sie nicht gefunden wird, gibt sie ein leeres Mono zurück. Dies funktioniert wie erwartet; Ich habe jedoch verschiedene Kombinationen von flatMap und (defaultIfEmpty und swithIfEmpty) ausprobiert, kann es aber nicht kompilieren / erstellen.
public Mono<User> insertUser(User user) {
return userRepository.findByUsername(user.username())
.flatMap(__ -> Mono.error(new DuplicateResourceException("User already exists with username [" + user.username() + "]")))
.switchIfEmpty(userRepository.insertUser(user));
}
Der Fehler, den ich bekomme, ist das Mono<Object> cannot be converted to Mono<User>
, also swithIfEmpty
scheint das nicht den entsprechenden Typ widerzuspiegeln und das Casting scheint auch nicht zu funktionieren.
Lösung
Nach weiteren Tests und unter Berücksichtigung der Antworten meiner Entwicklerkollegen bin ich bei der folgenden Lösung gelandet:
public Mono<User> insertUser(User user) {
return userRepository.findByUsername(user.username())
.flatMap(__ -> Mono.error(new DuplicateResourceException("User already exists with username [" + user.username() + "]")))
.switchIfEmpty(Mono.defer(() -> userRepository.insertUser(user)))
.cast(User.class);
}
Wie Thomas sagte, war der Compiler verwirrt. Meine Annahme ist, weil der flatMap
ein Mono mit einem Fehler switchIfEmpty
zurückgab und der ein Mono mit einem Benutzer zurückgab, sodass es zu einem Mono mit einem Objekt zurückkehrte (daher der zusätzliche .cast
Operator, um es zum Kompilieren zu bringen).
Die andere Ergänzung war das Hinzufügen der Mono.defer
in der switchMap
. Sonst hat der switchIfEmpty
immer geschossen.
Ich bin immer noch offen für andere Vorschläge / Alternativen (da dies so aussieht, als wäre es ein ziemlich häufiges Bedürfnis / Muster).
Beantwortet von – cgaskill
Antwort geprüft von – Clifford M. (FixError Volunteer)