当ConstraintValidator失败时突出显示无效字段

时间:2017-05-22 12:54:27

标签: jsf primefaces bean-validation

我想确保只通过WebUI输入1.1.1900和31.12.2100之间的日期值。因此,我创建了@Date注释和相应的验证器实现DateValidator.java

在我的实体类中,日期字段用@Date注释。每当我输入无效的日期值时,@Date注释中的默认消息将显示在全局<p:messages .../>中,但输入字段未标记为无效,因为输入空值时会执行此操作!

当我输入一个空值时,@ {No .NotNull验证在PROCESS_VALIDATION阶段失败,显示错误消息,输入字段突出显示,然后执行RENDER_RESPONSE阶段。

如果日期值无效,则会显示错误消息,但同时会执行UPDATE_MODEL_VALUESUPDATE_MODEL_VALUESRENDER_RESPONSE

Date.java

@Target({ElementType.METHOD,ElementType.FIELD,ElementType.ANNOTATION_TYPE,ElementType.CONSTRUCTOR,ElementType.PARAMETER})
@Retention(value = RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {DateValidator.class})
@Documented
public @interface Date {
    String message() default "Invalid Date";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

    @Target({ElementType.METHOD,ElementType.FIELD,ElementType.ANNOTATION_TYPE,ElementType.CONSTRUCTOR,ElementType.PARAMETER})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface List {
        Date[] value();
    }
}

DateValidator.java

public class DateValidator implements ConstraintValidator<Date, Calendar> {

    @Override
    public void initialize(Date date) {}

    /**
     * Returns {@code true}, if Date of Calendar is between 1.1.1900 and 31.12.2100
     *
     * @param calendar
     * @param constraintValidatorContext
     * @return
     */
    @Override
    public boolean isValid(Calendar calendar, ConstraintValidatorContext constraintValidatorContext) {
        if (Optional.ofNullable(calendar).isPresent()) {
            if (calendar.compareTo(minDate) == -1) {
                return false;
            }
            if (calendar.compareTo(maxDate) == 1) {
                return false;
            }
        }
        return true;
    }

    private static Calendar minDate = new GregorianCalendar(1900, 0, 1);
    private static Calendar maxDate = new GregorianCalendar(2100, 11, 31);
}

Entity.java

public class Entity {
    private java.util.Calendar date;

    @NotNull
    @Date
    @Temporal(TemporalType.TIMESTAMP)
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = MisEntity.DATETIME_PATTERN)
    @Column(name = "date", nullable = false)
    public java.util.Calendar getDate() {
        return date;
    }   
}

page.xhtml

<p:messages id="messages" autoUpdate="true" closable="true" showDetail="true"/>

<p:outputLabel for="date" ="#{bundle['date']}"/>
<p:calendar id="date" showButtonPanel="true" showOn="button"
            required="true"
            value="#{bean.date}"
            mask="true" pattern="dd.MM.yyyy HH:mm"> 
    <f:convertDateTime pattern="#{component.pattern}"/>
</p:calendar>

当我实现FacesValidator并对输入字段使用此验证器时,验证将失败PROCESS_VALIDATIONS中的无效值, 显示错误消息,突出显示无效字段,RENDER_RESPONSE是下一阶段。

DateValidator2.java

@FacesValidator("my.company.web.validation.DateValidator")
public class DateValidator implements Validator {

    @Override
    public void validate(FacesContext facesContext, UIComponent uiComponent, Object value) throws ValidatorException {
        boolean valid = false;
        if (Optional.ofNullable(value).isPresent() && value instanceof Date) {
            Calendar calendar = GregorianCalendar.getInstance();
            calendar.setTime((Date) value);
            valid = calendar.compareTo(minDate) != -1 && calendar.compareTo(maxDate) != 1;
        }
        if (!valid) {
            FacesMessage msg = new FacesMessage("Invalid date");
            msg.setSeverity(FacesMessage.SEVERITY_ERROR);
            throw new ValidatorException(msg);
        }
    }

    private static Calendar minDate = new GregorianCalendar(1900, 0, 1);
    private static Calendar maxDate = new GregorianCalendar(2100, 11, 31);

}

page2.xhtml

<p:messages id="messages" autoUpdate="true" closable="true" showDetail="true"/>

<p:outputLabel for="date" ="#{bundle['date']}"/>
<p:calendar id="date" showButtonPanel="true" showOn="button"
            required="true"
            value="#{bean.date}"
            mask="true" pattern="dd.MM.yyyy HH:mm"> 
    <f:convertDateTime pattern="#{component.pattern}"/>
    <f:validator validatorId="my.company.web.validation.DateValidator"/>
</p:calendar>

所以问题是,如何使用也突出显示无效输入字段的ConstraintValidator - 这应该是可能的,因为@NotNull会按预期执行此操作!

我有一个很大的域模型,我希望使用Calendar为每个@Date字段添加注释,我不希望使用<f:validator validatorId=".."/>

为每个输入字段添加验证器

0 个答案:

没有答案