Validation über ManagedBeans

Llois41

Mitglied
Hallo,

ich möchte aus einem Formular zum "Profil bearbeiten" die eingegebene Mail überprüfen. Standardmäßig steht die des angemeldeten Nutzers bereits im entsprechenden InputField. Beim Speichern soll u.a. dieses Feld auf 3 Sachen geprüft werden:

1. Ist die Mail noch die gleiche wie in der DB hinterlegt (keine Änderung)?
2. Ist die geänderte Mail noch nicht vergeben (Das Attribut ist kein Primärschlüssel, sollte trotzdem unique sein)
3. Sollte die Mail bereits vergeben sein, soll eine message ausgegeben werden, welche den Nutzer informiert.

So sieht das Feld im Formular aus:

HTML:
<b:column medium-screen="4">
                    <b:inputText id="mail" required="true"
                                 validatorMessage="Deine E-Mail-Adresse ist nicht gültig. Bitte gib Deine E-Mail-Adresse erneut ein!"
                                 requiredMessage="Deine E-Mail-Adresse ist nicht gültig. Bitte gib Deine E-Mail-Adresse erneut ein!"
                                 label="E-Mail" placeholder="name@example.com" value="#{profilManagedBean.mail}">
                        <f:validateRegex pattern="[\w\.-]*[a-zA-Z0-9_]@[\w\.-]*[a-zA-Z0-9]\.[a-zA-Z][a-zA-Z\.]*[a-zA-Z]"/>
                        <f:ajax event="blur" execute="mail" render="m_mail"/>
                    </b:inputText>
                    <b:messages id="m_mail" for="mail"/>
                </b:column>

So die Bean-Methode, welche über den Speichern-Button in dem "action"-Attribut übergeben wird:

Java:
public String update() {
        if (!nutzer.getPasswort().equals(tempPassword) && tempPassword != null && !tempPassword.isEmpty()) {
            nutzer.setPasswort(tempPassword);
        }
        if (mail.equals(nutzer.getMail())) {
            nutzer.addBezirk(dao.findBezirkByID(bezirkID));
            updateSprachen();
            updateFreizeitaktivitaeten();
            dao.merge(nutzer);
            refreshNutzer();
            return "home";

        } else if(validateMail(mail)){
            nutzer.addBezirk(dao.findBezirkByID(bezirkID));
            updateSprachen();
            updateFreizeitaktivitaeten();
            nutzer.setMail(mail);
            dao.merge(nutzer);
            refreshNutzer();
            return "home";
        }
            else {
            FacesContext.getCurrentInstance().addMessage("formProfil:mail", new FacesMessage(
                    "Diese Mail wird bereits verwendet!"));
            return "profil";
        }
    }


Das Problem ist in meinen Augen, dass ich bei der "update"-Methode immer einen String, also eine .xhtml-Seite zurückgeben muss und daher die Seite wahrscheinlich sogar nach Ausgabe der richtigen Fehlermeldung neu geladen wird. Diesen benötige ich aber, um nach erfolgreichem Speichern automatisch auf die Homepage zu gelangen.

Wie kann ich das umgehen?

Eine Alternative wäre keine Seite zurückzugeben, und damit auf die automatische Weiterleitung zu verzichten, oder?
 

Llois41

Mitglied

Ich habe jetzt versucht, das so umzusetzen, leider funktioniert auch das nicht.

Hier ist der Aufruf in der .xhtml:

HTML:
<b:inputText id="mail" required="true"
                                 requiredMessage="Bitte geben Sie Ihre E-Mail-Adresse an!"
                                 label="E-Mail" placeholder="name@example.com" value="#{registrierenManagedBean.nutzer.mail}">
                        <f:validator validatorId="mailValidatorRegistrieren"/>
                        <b:messages for="mail"/>
                    </b:inputText>

So sieht der Validator aus:

Java:
@FacesValidator("mailValidatorRegistrieren")
public class MailValidatorRegistrieren implements Validator {

    @EJB
    private DAO dao;
    private String mail;
    private static final Pattern EMAIL_PATTERN =
            Pattern.compile("^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,6}$", Pattern.CASE_INSENSITIVE);

    @Override
    public void validate(FacesContext facesContext, UIComponent uiComponent, Object o) throws ValidatorException {
        mail = (String)o;
        boolean matchesPattern = EMAIL_PATTERN.matcher(mail).find();

        if(!matchesPattern)
        {
            throw new ValidatorException((new FacesMessage("Ungültige E-Mail-Adresse","Bitte erneut eingeben!")));
        }

        if(mail.isEmpty()) {
            return;
        } else if(validateNutzer(mail)){
            throw new ValidatorException(new FacesMessage("Die E-Mail-Adresse ist bereits vergeben!"));
        } else{
            return;
        }

    }

    private boolean validateNutzer(String mail) {
        try {
            Nutzer n = dao.findNutzerByMail(mail);
            return n.getMail().equals(mail);
        } catch (NullPointerException e) {
            return false;
        }
    }
}

Und so die "findNutzerByMail"Methode in der DAO:

Java:
public Nutzer findNutzerByMail(String mail) {
        try {
            return em.createNamedQuery("findNutzerByMail", Nutzer.class)
                    .setParameter("mail", mail)
                    .getSingleResult();
        } catch (NoResultException e) {
            return null;
        }
    }

Das Problem ist, dass er nun trotz bereits existierender Mail in der DB einen Eintrag mit der gleichen Mail hinzufügt, dann aber direkt eine NonUniqueResultException wirft, da er ja nun 2 Einträge findet. Ich frage mich, wie das sein kann, denn eigentlich kommt die Validierung im JSF-Lebenszyklus doch vor der Invoke-Application-Phase und er müsste somit nach der Validierung abbrechen.

Sieht jemand den Fehler?
 

Llois41

Mitglied
Gleiches Problem, habe es nur erst mal auf die Registrieren-Seite verschoben. Allerdings funktioniert das nicht wie ich es mir vorstelle und ich weiß absolut nicht wieso..
 
Zuletzt bearbeitet:

stg

Top Contributor
Deine private validateNutzer Methode sieht falsch aus. Zum einen ist bei der Benennung völlig unklar, was denn der boolsche Rückgabewert überhaupt aussagen soll. Eigentlich willst du doch nur prüfen, ob es einen solchen Benutzer mit der übergebenen Mail-Adresse gibt?! Dann nenn die Methode doch auch so ... also etwa doesUserExistsWithMail(String mail) Darin braucht es nur eine Überprüfung à la return dao.findNutzerByMail(mail) != null
Die NullPointerException zu fangen und in diesem Fall einfach false zurückzugeben ist gefährlich. Bist du dir sicher, dass die EJB Injection deines DAO überhaupt funktioniert? Wenn nein, dann gibt die Methode ebenfalls false zurück. (Und keine Ahnung, ob das mit den neuesten Versionen mittlerweile geht, aber noch vor einiger Zeit war EJB Injection in JSF Validatoren technsich nicht möglich.)
Wenn du damit noch nicht weiterkommst, dann versuch doch bitte ein MCVE zu erstellen, die geposteten Code-Schnipsel zeigen das Problem möglicherweise gar nicht. Außerdem ist es mitunter wichtig zu wissen welche exakte Plattform du verwendest (welche JSF Version und welche Implementierung, welche EJB Version usw...)
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
E Struts XML validation schlägt immer fehl Web Tier 1
A JSF form absenden ohne require validation (andere schon) Web Tier 4
F JSF - Submit nach Validation-Failed Web Tier 6
K JSF Custom Validation Messages Migration von JSF 1.2 auf 2.0 Web Tier 5
J Validieren abhängiger Felder mit JEE6/Bean validation Web Tier 33
S Style bei fehlerhafter Eingabe (Bean Validation) ändern Web Tier 2
S Bean Validation (JSF 2.0) funktioniert nicht. Web Tier 4
L Struts 2 Iterator Validation Web Tier 4
D Ajax und Validation ohne große Umstrukturierung Web Tier 3
P Struts2 - Mehrere Methoden/Actions in einer Klasse + Validation Web Tier 2
L Struts Validation Error Web Tier 17
G Struts 2 Validation Web Tier 5
G Struts 2 - Validation Frage Web Tier 5
S Facelets Form: Validation abschalten bei Abbrechen-Button Web Tier 2
K Internationalisierung über Properties Datei Web Tier 6
P JSF ArrayList über InputText befüllen Web Tier 10
S Ich brauche Buchempfehlung über JSP und Servlet Web Tier 2
M JSF Actions über Methodenrückgabe? Web Tier 3
P JSP: Liste in Bean über Session aufbauen Web Tier 6
E JSF Applikation läuft nicht über Tomcat Web Tier 3
M Velocity - Dropdown-Felder über Macro generieren Web Tier 4
M Ton wiedergabe über jsp-Seite Web Tier 2
P For-Schleife mit JSTL über ArrayList Web Tier 8
R Datenbankzugriff über JSP mit JDBC connector ! Web Tier 2
G JSF h:form Tag Login über j_security_check und weiterleiten Web Tier 5
R Array oder Listen einlesen mit JSF über javaserverpage Web Tier 2
G Dateiupload über JSF? Web Tier 5
G Überblick über Web-Technologien Web Tier 2
M Authentifizierung über PhaseListener je nach Seite Web Tier 11
C ManagedBeans und Security Web Tier 6
M JSF Attribute von Komponenten aus ManagedBeans ändern? Web Tier 4
M JSF Kein Zugriff auf ManagedBeans, nach JSF Migration von 1.2 nach 2.0 Web Tier 4
M JSF JSF 2 ManagedBeans Web Tier 9
M ManagedBeans und Initialisierung Web Tier 4

Ähnliche Java Themen

Neue Themen


Oben