Wie behandelt oder wo fängt man z.B. NoResultException ab.

navino

Mitglied
Hallo,

ich stelle gerade eine Webanwendung von Hibernate auf JPA um, und stelle mir gerade die Frage was ich mit Exceptions vom Typ NoResultException oder generell mit Exceptions mache.

Habe also den klassischen Aufbau von Service und einer DAO Klasse.

@Override
public User getUser(String username, String password) {
try{
Query q = em.createQuery ("from User u where u.username = :username and u.password= :password");
q.setParameter("username",username);
q.setParameter("password",password);
return (User)q.getSingleResult();
}catch(NoResultException nre){
return null;
}
}

Wie mache ich das am Besten?

Gruß
navino
 
Jo, wenn du return null machst, musst du in der JavaDoc einfach schreiben "returns null, if no user with the given password was found" ;P

Was du mit anderen Exceptions machst, das ist ja fast schon eine "strategische Frage". Wir bei uns unterscheiden zwischen "business errors" und "system errors". Also business error ist "Passwort inkorrekt". System error ist "Datenbankweg". Business errors geben Meldungen an den Benutzer, System errors geben Meldungen an den Benutzer ("Sorry, da hat's uns was um die Ohren genauen"), plus eine entsprechende Meldung inkl. Stacktrace an den Produktverantwortlichen.

Zusatz 1: Für Webapplikationen kommt dann normalerweise und hoffentlich einfach die Meldung "Benutzername oder Passwort nicht korrekt" - vor Allem wenn der Benutzername eine E-Mailadresse ist, ist es von Vorteil, einem "Angreifer" nicht mitzuteilen, ob die E-Mail jetzt existiert oder nicht.

Zusatz 2: Wir bei uns machen für "logging purpose" immer gerne zuerst einen select mit der where-clause auf den Benutzernamen und dann einen select mit der where-clause auf den Benutzernamen und das Passwort.

Zusatz 3: Bitte das Passwort in der Datenbank verschlüsselt als Hash ablegen =(

Gruss
slowy
 
Hallo,

das mit Unterscheidung nach business und system-errors ist soweit klar. Ich werde die jetzt mit AOP versuchen abzufangen. Bei einer NoResultException werde einfach gar nicht machen und an den Aufrufer null zurückwerfen. Die NoResultException darf aus der DAO-Schicht auch gar nicht raus... denke ich.

Das mit dem Passwort verschlüsseln und so ist klar


Gruß
navino
 
Moinmoin

Also ich habe ja selten was AOP-mässiges gemacht, aber wäre das in diesem Fall nicht die falsche Wahl? Wir benutzen solche sachen und Transaktionen zu starten/committen/rollbacken, ObjectPools zu verwalten oder um Zeiten zu loggen. Dein Fall hat schon eher etwas mit business logic zu tun.

Ich sehe kein Problem, wenn der DAO in diesem Fall einfach null zurückgibt und der Layer obendran einfach
if(user == null){msg = "sorry, du gommsch hier ned rein!"}else{machstdulogin()}
macht,...

gruss
slowy
 
Hallo,

die Trennung zwischen fachlicher- und technischer Ausnahme finde ich auch eine gute Lösung. Wobei es manchmal nicht so einfach zu entscheiden ist, ob eine Exception nun nur technisch oder doch fachlich ist. Um dort flexible zu bleiben bieten sich generische Mechanismen zur "Übersetzung" einer Ausnhame in einen anderen Ausnahme-Typ an. Im Springframework gibt es dafür beispielsweise die ExceptionTranslator Abstraktion.

Btw. eine Alternative zum Werfen einer Ausnahme oder der einfachen Rückgabe von "null" wäre die Einführung eines expliziten Null-Objects. Konkret definiert man so etwas wie einen NullUser / NotExistingUser / EmptyUser (extends User, als Singleton) und gibt in dem Fall eines nicht vorhandenen Users die Instanz des NullUsers zurück. Verwendet man dieses Pattern hat man im Code keine expliziten Null-Checks mehr, dies erlaubt etwas schlankeren Code.

Gruß Tom
 
Hallo,

das mit dem ExceptionTranslator schaue ich mir mal an. Ich bin eigentlich grundsätzlich der Meinung, das die DAO-Exceptions alla NoResultException eigentlich nicht aus dem DAO oder spätestens nicht nach dem Service weitergereicht werden dürfen. Hier müsste eine Überstzung in einen anderen Typ und eigentlich auch noch sprachunabhängig geworfen werden.....

Das mit "EmptyUser" Object schaue ich mit auch mal an...... Aber dann müsste ich ja bei Null anstatt auf Null auf das EmptyObjekt abfragen....Was habe ich da gwonnen? Gibt es da irgendwo ein kleines Beispiel?

Gruß
navino
W
 
Hallo,

Das mit "EmptyUser" Object schaue ich mit auch mal an...... Aber dann müsste ich ja bei Null anstatt auf Null auf das EmptyObjekt abfragen....Was habe ich da gwonnen? Gibt es da irgendwo ein kleines Beispiel?
Ob man null durch Anwendungscode durchschleifen sollte oder nicht ist so ein bisschen eine philosophische Frage. Die Motivation dazu kann man an vielen Stellen nachlesen. Beispiele wären http://code.google.com/p/guava-libraries/wiki/UsingAndAvoidingNullExplained
http://cs.oberlin.edu/~jwalker/nullObjPattern/

Wenn du bei loadUserByName null zurück gibst kann das mehrere Gründe haben...
Gab es einen Fehler beim Abfragen der Datenbank der behandelt wurde ?
Gab es den User nicht?
Gab es mehrere User?

Gibst du explizit NotExistingUser zurück ist klar welcher Fall aufgetreten ist.
Kommt null zurück impliziert dies, das ein Fehler aufgetreten ist. Das geht dann einher mit der philosophie Fail-Fast -> Bei Fehler so früh wie möglich aussteigen um darauf auch so früh wie möglich aufmerksam zu werden.

Beispiele für Null-Objects in der JRE Standard-Bibliothek wären z.B. Collections.EMPTY_LIST, Collections.EMPTY_SET, Collections.EMPTY_MAP.

Gruß Tom
 
Zurück