JSF Fehlermeldungausgabe

fsicher

Bekanntes Mitglied
Hallo allerseits

Ich möchte sicherstellen, dass die Eingabe in ein Feld getätigt wird. Beispiel mit Benutzername-Textfeld:

Java:
<h:inputText id="username" value="#{loginBean.username}" required="true">
    <f:validateLength minimum="1" />
</h:inputText>
<h:message for="username" style="color:red; font-size:75%" />

Bei fehlender Eingabe wird die folgende Meldung ausgegeben:

[XML]
loginForm:username: Überprüfungsfehler: Wert ist erforderlich.
[/XML]

Ich möchte aber nur den letzen Teil (Wert ist erforderlich) anzeigen lassen.

Ich habe versucht, die Meldung zu überschreiben:

[XML]
javax.faces.validator.LengthValidator.MINIMUM=Wert ist kürzer als das erlaubte Minimum von {0} Zeichen.
[/XML]

Aber, die Verweise auf Komponenten wurden weiterhin (mit meiner Meldung) angezeigt. Kann man den vorderen Teil (loginForm:username:Überprüfungsfehler) irgendwie auslassen, ohne dass man die Fehlerbehandlung im ManagedBean macht? Müsste ich selber eine Validator-Klasse schreiben? Und falls ja, wie stelle ich sicher, dass die Mehrsprachigkeit weiterhin unterstützt wird?

Danke.
 

nocturne

Bekanntes Mitglied
Viele weitreichende Fragen :D

Also du könntest z.B. in deiner Login-Bean schreiben
Java:
public void usernameValidate(FacesContext ctx, UIComponent comp,
    Object value) throws ValidatorException {
  if (value instanceof String) {
    String strValue = (String) value;
    if (strValue.length() >= 1) {
      return;
    }
  }

  throw new ValidatorException(
          new FacesMessage("{illegal_login}", null));

}

und in den Resources_de_DE.properties:
SQL:
illegal_login=Wert ist erforderlich.

In deiner xhtml dann:
<h:input text="#{loginbean.username}" validator="#{loginbean.usernameValidator}"/>

Die beste Lösung beitet aber immernoch Richfaces mit
Java:
@NotNull
private String username;
 
Zuletzt bearbeitet:
M

maki

Gast
@nocturne
Letzteres wird doch schon von JSR 303 abgedeckt/zur Verfügung gestellt und sollte damit unabhängig von der konkreten JSF 2 Implementierung sein?
 

nocturne

Bekanntes Mitglied
Richtig. Auf RF3 bezog ich mich wegen dem tag r:beanValidator. Den sucht man ja in JSF12 vergeblich, erst bei JSF2 kommt es als validateBean zurück.
 

fsicher

Bekanntes Mitglied
Vielen Dank.

Zuerst zur Annotation @NotNull:

Ich benutze Mojarra-2.0.3-FCS. Ob diese Annotation in Mojarra auch unterstützt wird ...

Wenn ich sie einsetze, wird einzig import com.sun.istack.internal.NotNull; vorgeschlagen. Das wird aber wohl kaum diese Annotation sein?

Folge:
Ich habe mich vorerst für die erste Variante (validate-Methoden) entschieden. Hier noch kurz der relevante Code-Auszug:

Bean-Klasse:
Java:
@ManagedBean(name = "loginBean")
@SessionScoped
public class UserLoginBean {

	private String username;
	private String password;

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	/* Username-Validierung */
    public void validateUsername(FacesContext ctx, UIComponent comp,
			Object value) throws ValidatorException {
		if (value instanceof String) {
			String strValue = (String) value;
			if (strValue.length() >= 2) {
				return;
			}
		}

		Locale l = FacesContext.getCurrentInstance().getExternalContext()
				.getRequestLocale();
		ResourceBundle bundle = ResourceBundle
				.getBundle("resources.bundle.messages_" + l.getLanguage());
		String msg = bundle.getString("username_empty");
		
		throw new ValidatorException(new FacesMessage(msg, null));
	}

    /* Password-Validierung */
	public void validatePassword(FacesContext ctx, UIComponent comp,
			Object value) throws ValidatorException {
		if (value instanceof String) {
			String strValue = (String) value;
			if (strValue.length() >= 2) {
				return;
			}
		}

		Locale l = FacesContext.getCurrentInstance().getExternalContext()
				.getRequestLocale();
		ResourceBundle bundle = ResourceBundle
				.getBundle("resources.bundle.messages_" + l.getLanguage());
		String msg = bundle.getString("password_empty");
		
		throw new ValidatorException(new FacesMessage(msg, null));
	}

	public String checkLogin() {

		// ...
	}
}

Die login-Datei:
[XML]<h:form id="loginForm">
<h:panelGrid columns="3" columnClasses="contentRight">
<h:eek:utputText style="align:right" value="#{msg.lbl_username}"></h:eek:utputText>
<h:inputText id="username" value="#{loginBean.username}" validator="#{loginBean.validateUsername}" />
<h:message for="username" style="color:red; font-size:75%" />

<h:eek:utputText style="align:right" value="#{msg.lbl_password}"></h:eek:utputText>
<h:inputSecret id="password" value="#{loginBean.password}" validator="#{loginBean.validatePassword}" />
<h:message for="password" style="color:red;font-size:75%"/>

<h:eek:utputText style="align:right" value=" " />
<h:commandButton value="#{msg.btn_login}"
action="#{loginBean.checkLogin}" />
</h:panelGrid>
</h:form>[/XML]

Die messages.properties (default):
[XML]# Validierung
username_empty=Benutzername eingeben
password_empty=Kennwort eingeben[/XML]

Das Problem ist, dass die Validierung der Eingabe nur gemacht dann gemacht wird, wenn mindestens ein Zeichen im entsprechenden InputText-Feld eingegeben wurde. Heisst, leere Felder fürhren zu keiner Validierung: die Methode checkLogin wird mit null-Werten aufgerufen und leitet die Ausführung zur Error-Page weiter.

Kann man dies verhindern, ohne dass ich aus checkLogin die Validierungsmethode explizit aufrufen muss?

##### EDIT #####

Habe es vorläufig wie folgt gelöst:

[XML]
<h:inputText id="username" value="#{loginBean.username}" required="true" requiredMessage="#{msg.username_empty}" validator="#{loginBean.validateUsername}" />[/XML]

Und mit msg wird das Ressourcen-Bündel angesprochen (konfiguriert in faces-config.xml).

Gebe es eine bessere Variante?
 
Zuletzt bearbeitet:

nocturne

Bekanntes Mitglied
Du brauchst das Locale und ResourceBundle eigentlich nicht es würde
Java:
throw new ValidatorException(new FacesMessage("{msg.username_empty}", null));
reichen.

Mit Locale und ResourceBundle zumzuspielen ist ganz ganz gefährlich weil du ewig warten musst!
 

fsicher

Bekanntes Mitglied
Danke.

Habe es geändert und es hat funktioniert. Aber, die Notation verstehe ich nicht ganz :noe:

Das hier funktioniert:

Java:
throw new ValidatorException(new FacesMessage("{msg.username_empty}", null));

Aber, auch das folgende (ohne { bzw. })funktioniert:

Java:
throw new ValidatorException(new FacesMessage("msg.username_empty", null));

Ist das jetzt bei mir ein "Zufall", oder gibt es dafür eine Erklärung bzw. ist mir etwas entgangen? Haben die geschweiften Klammer hier eine spezielle Bedeutung?
 

fsicher

Bekanntes Mitglied
Irgendwie funktioniert das mit dem Überschreiben von Fehlermeldungen (Converter / Validator) nicht ganz ???:L

Folgendes Beispiel:

[XML]
<h:eek:utputText value="#{msg.lbl_zip}" />
<h:inputText id="zip" value="#{addUserBean.zip}" required="true">
<f:convertNumber />
<f:validateLongRange minimum="999" maximum="999999" />
</h:inputText>
<h:message for="zip" style="color:red;text-align:left" />
[/XML]

Die Einträge in der messages_en.properties sehen wie folgt aus:
[XML]
javax.faces.component.UIInput.REQUIRED={0}: Validation Error: VALUE IS REQUIRED.
javax.faces.converter.NumberConverter.NUMBER={2}: ''{0}'' is not a NUMBER.
javax.faces.converter.NumberConverter.NUMBER_detail={2}: ''{0}'' is not a NUMBER. Example: {1}
javax.faces.validator.LongRangeValidator.MAXIMUM={1}: Validation Error: Value is greater than allowable MAXIMUM of ''{0}''
javax.faces.validator.LongRangeValidator.MINIMUM={1}: Validation Error: Value is less than allowable MINIMUM of ''{0}''
javax.faces.validator.LongRangeValidator.NOT_IN_RANGE={2}: Validation Error: Specified attribute is not between the expected VALUES of {0} and {1}.
[/XML]

Ich habe in jeder Meldung ein Wort GROSS geschrieben, um es besser zu erkennen, wenn es funktioniert. Ansonsten habe ich die Einträge aus der Datei javax.faces.Messages_en.properties kopiert, die in der jsf-api.jar zu finden ist.

Wenn ich die eingabe für ZIP (Postleitzahl) weglasse, oder Buchstaben eingebe oder was auch immer: er kommt immer mit der Meldung aus der Original-Property-Datei. Meine Datei (messages_en.properties) ignoriert er vollständig. Natürlich kann ich hier requiredMessage="msg.xxx" auch direkt ausgeben, aber das Problem mit Zahl-Konvertierung bzw. Bereichüberprüfung bleibt.

Wieso zeigt er meine (überschriebene) Meldungen nicht an? Woran liegt es?
 
Zuletzt bearbeitet:

fsicher

Bekanntes Mitglied
Die messages_en.properties wird gefunden, denn für alle andere Felder wird jeweils die in der messages_en.properties definierte Meldung ausgegeben, wenn sie leer bleiben.

Sonst liegt die Datei in (eclipse) src.resource.bundle Verzeichnis und ist in der faces-config.xml wie folgt registriert:

[XML]
<resource-bundle>
<base-name>resources.bundle.messages</base-name>
<var>msg</var>
</resource-bundle>
[/XML]
 

Neue Themen


Oben