Валидаторы и конвертеры

Главной целью конвертации и валидации является проверка и подготовка данных для обновления значений managed bean компонента. То есть, перед вызовом методов обновления значений, можно сделать определенные выводы о состоянии данных. Это позволяют сконцентрироваться на бизнес-логике приложения, а не на проверках введенных значений типа проверки размера строки, соответствия текстового значения заданному типу и т.д.

Для применения конвертеров и валидаторов необходимо подключить соответствующий namespace. В следующем коде показано подключение к странице namespace типа core с алиасом 'f' :

<html 
   xmlns="http://www.w3.org/1999/xhtml" 
   xmlns:f="http://java.sun.com/jsf/core" >

Валидатор Validator

Для проверки значений полей формы на валидность можно использовать либо стандартные валидаторы, встроенные в JSF, либо создать собственный, наследующий свойства Validator. Порядок подключения валидатора описан на странице стандартных JSF компонентов.

Стандартные валидаторы : DoubleRangeValidator, LongRangeValidator, LengthValidator

JSF включает в себя три стандартных компонента для валидации:

ВалидаторОписание
DoubleRangeValidator Проверка числового значения : значение компонента должно быть числом и находиться в интервале, определяемым нижней и верхней границами. Интервал может быть не определен или включать только одно граничное значение.
LongRangeValidator Проверка целочисленного значения : значение компонента должно быть числом и находиться в интервале, определяемым нижней и верхней границами. Интервал может быть не определен или включать только одно граничное значение.
LengthValidator Проверка текстового значения : размер строки должен находиться в интервале, определяемым нижней и верхней границами. Интервал может включать только одно граничное значение.

Валидатор кода проверки размера строки

<h:form>
    <h:message for="username" style="color:red" />
    <h:inputText id="username" value="#{user.username}" 
                 size="20" required="true" label="Пользователь">
        <f:validateLength minimum="5" maximum="10" />
    </h:inputText>
</h:form>

В примере если размер строки не будет находиться в пределах от 5 до 10 символов, то в интерфейсе страницы в позиции с тегом <h:message> будет выведено соответствующее сообщение. Локализация сообщения фреймворка JSF описана здесь.

Проверка на валидность в компонентах, реализующих интерфейс Validator

Код класса валидатора EmailValidator, реализующего интерфейс Validator :

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.faces.component.UIComponent;
import javax.faces.application.FacesMessage;

import javax.faces.context.FacesContext;

import javax.faces.validator.Validator;
import javax.faces.validator.FacesValidator;
import javax.faces.validator.ValidatorException;

@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;

    public EmailValidator()
    {
        pattern = Pattern.compile(EMAIL_PATTERN);
    }

    @Override
    public void validate(FacesContext context, UIComponent component,
                         Object value) throws ValidatorException
    {
        Matcher 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);
        }
    }
}

Пример подключения валидатора : EmailValidator

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

Конвертер данных, Converter

JSF предоставляет набор конвертеров для преобразования значений компонентов UIComponent с присвоением значения свойству managed bean объекта. Конвертер данных может преобразовать текстовое значение поля в значение определенного типа с проверкой формата. При возникновении ошибки вызывается исключение.

JSF позволяет использовать как встроенные, так и специально созданные конвертеры данных, которые представляют собой java-классы, наследующие свойства javax.faces.convert.Converter. Порядок подключения конвертера представлен на странице стандартных JSF компонентов

В JSF 2.0 можно использовать следующие конвертеры :

КонвертерРеализующий класс
convertNumber Конвертирование текстового значения в число заданного формата.
convertDateTime Конвертирование текстового значения в тип Date заданного формата.
converterПользовательский Convertor.

Рассмотрим пример создания собственного конвертера URL. В класса managed bean, наследующего свойства Converter, необходимо переопределить два метода getAsObject(), getAsString().

Листинг managed bean компонента URLConverter :

import javax.faces.context.FacesContext;
import javax.faces.component.UIComponent;

import javax.faces.application.FacesMessage;

import javax.faces.convert.Converter;
import javax.faces.convert.FacesConverter;
import javax.faces.convert.ConverterException;

import org.apache.commons.validator.UrlValidator;
 
@FacesConverter("URLConverter")
public class URLConverter implements Converter
{
    private final String HTTP = "http://";
    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value)
    {
        StringBuilder url = new StringBuilder();
        // Если строка не начинается с http://, то добавляем
        if (!value.startsWith(HTTP, 0))
            url.append(HTTP);

        url.append(value);

        // Используем Apache URL validator для проверки 
        UrlValidator urlValidator = new UrlValidator();
        // Если формат URL нарушен, то создаем сообщение об ошибке
        if (!urlValidator.isValid(url.toString())){
            FacesMessage msg = new FacesMessage ("Ошибка конвертации URL.", 
                                                 "Неправильный формат URL.");
            msg.setSeverity(FacesMessage.SEVERITY_ERROR);
            throw new ConverterException(msg);
        }

        URLBookmark urlBookmark = new URLBookmark(url.toString());

        return urlBookmark;
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {

        return value.toString();
    }
}

Листинг managed bean компонента "user", содержащего поле url. Для простоты остальные поля не рассматриваем.

import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
 
@ManagedBean(name="user")
@SessionScoped
public class BeanUser implements Serializable
{
    String url;

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }
}

Фрагмент кода страницы с подключением пользовательского конвертера данных URLConverter :

<h:body>
    <h1>Конвертор JSF 2.0</h1>
    <h:form>
        <h:panelGrid columns="2">
            <h:outputLabel id="lblURL" for="url" value="Введите URL :" />
            <h:inputText id="url" value="#{user.url}" required="true" >
                <f:converter converterId="URLConverter" />
            </h:inputText>
            <h:message for="url" style="color:magenta" />
        </h:panelGrid>

        <h:commandButton value="Сохранить" action="save" />
    </h:form>
</h:body>

Примеры использования конвертеров данных convertDateTime, convertNumber

Пример кода подключения стандартного конвертера даты convertDateTime. Форматирование значения поля дня рождения birthDate выполняется по шаблону, как определено в классе java.text.SimpleDateFormat

<h:message for="birthDate" errorClass="errorMessage" />

<h:outputLabel value="День рождения" for="birthDate" />
<h:inputText id="birthDate" value="#{contactBean.birthDate}">
    <f:convertDateTime dateStyle="short" pattern="dd.mm.yyyy"/>
</h:inputText>

Пример использования стандартного конвертера числового значения convertNumber:

<h:message for="total" errorClass="errorMessage" />

<h:outputText value="123.45678" >
    <f:convertNumber pattern="#000.000" />
</h:outputText>

<h:outputText id="total"  value="orderBean.total" required="true" >
    <f:convertNumber minFractionDigits="4" />
</h:outputText>
  Рейтинг@Mail.ru