26 Mart 2015 Perşembe

JSF custom validator

JSF'de custom validation neden gerekli?



JSF life cycle'da 3. aşamaya denk gelen validation, neden gerekli?
Bir uygulamanın işleyişi genellikle girdi ile başlar. Girdinin yanlış ya da kötü niyetli olması ise bazen öngörülemeyen sorunlara neden olabilir.
Özellikle kurumsal uygulamalarda yapılan işlemlerin hassasiyetinden dolayı girilen verinin düzgün ve güvenli olduğundan emin olunması gerekir. Bu yüzden validation yapılır.
Validation başarısız olduğunda hemen kullanıcıya cevap dönülür. Girdi hatalı olduğunda direk 6.aşamaya yani render response aşamasına geçilmesiyle zaman ve performans kaybı yaşanmamış olur.

İşte bu yüzden JSF ile yazılan web applicationlarda girdilerin kontrolünü dikkatli yapmak gerekiyor.
Bunun için JSFde validation için tanımlanmış taglar var. Örneğin f:validateLength tagı ile girdinin uzunluğunu kontrol edebiliriz. Fakat bu gibi hazır taglar her zaman işe yaramayabiliyor.
Örneğin bir e-posta adresinin geçerli olup olmadığını bu tagları kullanarak kontrol edemiyoruz.
Bu gibi karmaşık kontroller için custom validator yazmak şart oluyor. Regular expressionları duruma göre kullanarak her türlü senaryoya uygun validatorlar yazabiliyoruz.

JSF de custom validation yazmak


1. javax.faces.validator.Validator arayüzünü implement eden yeni bir validator classı yazarız.

2. validate() metodunu override ederiz.
Bunun için Pattern ve Matcher classları aracılığıyla regular expressionları kullanabiliriz.
Pattern match etmemesi durumunda FacesMessage ile hata mesajı gösteririz.

3. @FacesValidator annotationı ekleriz.

4. JSF componenti içerisinde <f:validator> tagı ile kullanabiliriz.

Örnek uygulama

EmailValidator.java
...

@FacesValidator("EmailValidator")
public class EmailValidator implements Validator{
 
 private static final String EMAIL_PATTERN = "^[_A-Za-z0-9-]+(\\." +
   "[_A-Za-z0-9-]+)*@[A-Za-z0-9]+(\\.[A-Za-z0-9]+)*" +
   "(\\.[A-Za-z]{2,})$";
 
 private Pattern pattern;
 private Matcher matcher;
 
 public EmailValidator(){
    pattern = Pattern.compile(EMAIL_PATTERN);
 }
 
 @Override
 public void validate(FacesContext context, UIComponent component,
   Object value) throws ValidatorException {
 
  matcher = pattern.matcher(value.toString());
  if(!matcher.matches()){
 
   FacesMessage msg = 
    new FacesMessage("E-mail validation failed.", 
      "Invalid E-mail format.");
   msg.setSeverity(FacesMessage.SEVERITY_ERROR);
   throw new ValidatorException(msg);
 
  }
 
 }
}


login.xhtml
...

<h:inputText id="email" value="#{user.email}" 
   size="20" required="true" label="Email Address">
 
 <f:validator validatorId="EmailValidator" />
 
</h:inputText>
<h:message for="email"/>
...

Nasıl çalışır?

Form gönderildiğinde container'ın service() metodu validasyonu sorguluyor. Yani validate() metoduna bakıyor. Eğer validasyon başarısız olursa ManagedBean hiç yaratılmıyor. Direk kullanıcıya mesaj gösteriyor. Hem performans hem de güvenlik açısından doğru bir yaklaşım olmuş oluyor.

Hiç yorum yok:

Yorum Gönder