piątek, 6 stycznia 2012

Własny walidator w JSF 2

Przygotowując aplikację AccountApplicationForm do zbierania wniosków na potrzeby projektu SOAwA potrzebowałem na komponencie h:inputText zweryfikować czy to co użytkownik wprowadzi jest poprawne. Konkretnie chciałem sprawdzić czy wprowadzony numer PESEL jest poprawny.

Nie jest to standardowa walidacja dostępna w JSF. Na szczęście framework udostępnia mechanizm rozszerzania domyślnych walidatorów - interfejs javax.faces.validator.Validator.

Poniżej przedstawiam implementację walidatora dla numeru PESEL:

   1:  package pl.com.mbsoftware.soa.banksourcesystem.application.web;
   2:   
   3:  import javax.faces.application.FacesMessage;
   4:  import javax.faces.component.UIComponent;
   5:  import javax.faces.context.FacesContext;
   6:  import javax.faces.validator.FacesValidator;
   7:  import javax.faces.validator.Validator;
   8:  import javax.faces.validator.ValidatorException;
   9:   
  10:  @FacesValidator("PeselValidator")
  11:  public class PeselValidator implements Validator {
  12:   
  13:      private static int[] WEIGHTS = new int[] { 1, 3, 7, 9, 1, 3, 7, 9, 1, 3 };
  14:   
  15:      @Override
  16:      public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
  17:          if (!isPesel(value.toString())) {
  18:              FacesMessage msg = new FacesMessage("PESEL validation failed", "Invalid PESEL");
  19:              msg.setSeverity(FacesMessage.SEVERITY_ERROR);
  20:              throw new ValidatorException(msg);
  21:          }
  22:      }
  23:   
  24:      private boolean isPesel(String pesel) {
  25:          if (pesel.length() != 11) {
  26:              return false;
  27:          }
  28:          int sum = 0;
  29:          int currentCheck = 0;
  30:          int check = new Integer(pesel.substring(pesel.length() - 1));
  31:          for (int i = 0; i < pesel.length() - 1; i++) {
  32:              sum += new Integer(String.valueOf(pesel.charAt(i))) * WEIGHTS[i];
  33:          }
  34:          currentCheck = 10 - (sum % 10);
  35:          if (currentCheck > 9) {
  36:              currentCheck = 0;
  37:          }
  38:          return (currentCheck == check);
  39:      }
  40:   
  41:  }


Dzięki adnotacji @FacesValidator (linia 10) kontener JSF informowany jest o tym, że klasa definiuje walidator, który można wykorzystać w szablonach stron. W linii 11 zaznaczamy, że klasa implementuje w/w interfejs. Interfejs wymusza implementację metody validate - linie 16-22. Linie 18-20 prezentują budowanie komunikatu i wyjątku w przypadku, gdy walidacja zakończy się negatywnie - najpierw budowany jest odpowiedni komunikat, który następnie zostaje oznaczony poziomem błędu, by na końcu został on wyrzucony z wyjątkiem ValidatorException.

Tak zdefiniowany komponent walidacyjny można wykorzystać w poniższy sposób:
   1:  <h:inputText id="peselId"
   2:      value="#{applicationPresenter.application.customer.pesel}"
   3:      label="Pesel">
   4:      <f:validator validatorId="PeselValidator" />
   5:  </h:inputText>

Linia 4 zawiera deklarację wykorzystania walidatora dla komponentu h:inputText. Deklarując walidator należy podać jego identyfikator, zgodny z @FacesValidator.

Brak komentarzy:

Prześlij komentarz