跨字段Java Bean验证不验证JSF中的字段

时间:2016-10-25 21:10:35

标签: java primefaces jsf-2 bean-validation

我正在尝试使用DateRange验证器来实现验证,如果开始日期在结束日期之前。我已经为验证,验证器类等定义了注释。当我尝试在验证对象(通过UI)中访问或设置某些内容时,不会因为验证而不通过验证。我究竟做错了什么 ?我已经定义了以下类:

TimePeriod.java

@Constraint(validatedBy = DateRangeValidator.class)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface TimePeriod {

     String message() default "something";
        Class<?>[] groups() default {};
        Class<? extends Payload>[] payload() default {};

}

DateRangeValidator.java

    public class DateRangeValidator implements ConstraintValidator<TimePeriod, DateRange>{

    TimePeriod constraintAnnotation;

    @Override
    public void initialize(TimePeriod constraintAnnotation) {
        this.constraintAnnotation = constraintAnnotation;
    }

    @Override
    public boolean isValid(DateRange value, ConstraintValidatorContext context) { 
            throw new RuntimeException("Some exception");

    }
}

DateRange.java

public class DateRange {

    private Date startDate;
    private Date endDate;

    public DateRange(Date start, Date end){
        this.startDate = start;
        this.endDate = end;
    }

    public Date getStartDate() {
        return startDate;
    }
    public void setStartDate(Date startDate) {
        this.startDate = startDate;
    }
    public Date getEndDate() {
        return endDate;
    }
    public void setEndDate(Date endDate) {
        this.endDate = endDate;
    }

}

我使用Primefaces日历元素来选择开始日期和结束日期。这个片段是:

<p:calendar id="startdateWizard"    
            value="#{DRBean.dateRange.startDate}"
            showButtonPanel="true"
            required="true"
>

DRBean.java

@Named
@ViewScoped
public class PFSBean implements Serializable {

    @TimePeriod
    private DateRange dateRange = new DateRange(new Date(), new Date()) ;


  public DateRange getDateRange() {
    return dateRange;
  }

  public void setDateRange(DateRange dateRange) {
    this.dateRange = dateRange;
  }
}

可能是因为没有直接设置dateRange对象 - 只设置了其中一个字段。如果是这样,如何更改它以达到预期效果(验证DateRange对象以确保开始日期始终在结束日期之前)

1 个答案:

答案 0 :(得分:1)

经过一些研究后,我意识到对于这种跨领域验证,使用JSR303 bean验证,需要在类级别进行验证。不幸的是,直到JSF 2.3版本这个选项不可用,因为它在post中说明。因此仅使用JSF是不可能的。然而,Omnifaces的帮助很少。可以在Omnifaces showcase上找到类级别验证的绝佳示例。将此解决方案应用于我的任务就像在带有日历元素的表单中添加<o:validateBean value="#{pFSBean.dateRange}"/>一样简单:

    <h:form>
        <p:messages id="messages" autoUpdate="true"/>
        <p:panel id="panel1">
            <h:panelGrid columns="2">
                <p:calendar id="startdateWizard"    
                            value="#{pFSBean.dateRange.startDate}"
                            showButtonPanel="true"
                            required="true"
                >   
                </p:calendar>
                <p:calendar id="enddateWizard"
                            name="enddateWizard"
                            value="#{pFSBean.dateRange.endDate}"
                                    required="true" showButtonPanel="true"
                >                           
                </p:calendar>
            </h:panelGrid>
        </p:panel>        
        <o:validateBean value="#{pFSBean.dateRange}"/> 
        <p:commandButton process="@(form)" update="@(form)" 
                             value="Process form"/>

   </h:form>

此外,@TimePeriod注释在课程级别上移动:

@TimePeriod
public class DateRange {
   ....
   ....
}

应在注释定义中添加TYPE的注释目标。就这样。现在将调用验证器类中的方法isValid。当然这不是完美的解决方案,因为需要额外的工具,但遗憾的是不可能