Revision history [back]

click to hide/show revision 1
initial version

asked 2015-06-30 02:00:15 +0800

ghostomg gravatar image ghostomg flag of Indonesia

Class Level Constraint BeanValidator

I'm using ZK 7.0.3 MVVM, Is that possible to integrated class level constraint to MVVM Zul just like usual (@validator('beanValidator'))?

This is snipset of Zul component:

<intbox id="ibQty" width="200px" 
  value="@bind(fx.qty) @validator('beanValidator')" 
  errorMessage="@load(vmsgs[self])"/>

This is snipset of class level constraint Entity:

@Entity
@AllowFractional(allowedStateProperty = "allowedFractional", 
                 valueProperty = "qty", 
                 message = "Qty can't have fractional")
public class TbInvUserreqDetail implements Serializable {
    //... Others field ...

    @Column(name = "allowedfractional")
    private Boolean allowedFractional = false;

    @Column(name = "qty")
    @NotNull(message = "Qty can't empty.")
    private double qty;

    //... setter getter ...
}

This is snipset of custom validator 'AllowFractional' interface:

@Target({ElementType.METHOD, ElementType.TYPE, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = AllowFractionalValidator.class)
@Documented
public @interface AllowFractional {
    String message() default "{default message}";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
    String allowedStateProperty();      
    String valueProperty();    

    @Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @interface List {
        AllowFractional[] value();
    }
}

This is the implemented validator class:

public class AllowFractionalValidator implements ConstraintValidator<AllowFractional, Object> {
    private String allowedStateProperty;
    private String valueProperty;
    private String msg;

    @Override
    public void initialize(AllowFractional a) {
        this.allowedStateProperty = a.allowedStateProperty();
        this.valueProperty = a.valueProperty();
        this.msg = a.message();
    }

    @Override
    public boolean isValid(Object obj, ConstraintValidatorContext context) {
        try {
            Boolean allowedState = Boolean.valueOf(BeanUtils.getProperty(obj, this.allowedStateProperty));
            Double value = Double.valueOf(BeanUtils.getProperty(obj, this.valueProperty));

            if (allowedState) {
                return true;
            } else {
                Double fractionalPart = value % 1;
                Double integralPart = value - fractionalPart;
                if (Double.compare(0d, fractionalPart) >= 0) {
                    return true;
                } else {
                    context.disableDefaultConstraintViolation();
                    context.buildConstraintViolationWithTemplate(msg).addPropertyNode(valueProperty)
                            .addConstraintViolation();
                    return false;
                }
            }
        } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException ex) {
            Logger.getLogger(AllowFractionalValidator.class.getName()).log(Level.SEVERE, null, ex);
            context.disableDefaultConstraintViolation();
            context.buildConstraintViolationWithTemplate(msg).addPropertyNode(valueProperty)
                    .addConstraintViolation();
            return false;
        }
    }
}

Could it return the constraint error to ibQty component's errorMessage? Thank you.

Class Level Constraint BeanValidator

I'm using ZK 7.0.3 MVVM, Is that possible to integrated class level constraint to MVVM Zul just like usual (@validator('beanValidator'))?

This is snipset of Zul component:

<intbox id="ibQty" width="200px" 
  value="@bind(fx.qty) @validator('beanValidator')" 
  errorMessage="@load(vmsgs[self])"/>

This is snipset of class level constraint Entity:

@Entity
@AllowFractional(allowedStateProperty = "allowedFractional", 
                 valueProperty = "qty", 
                 message = "Qty can't have fractional")
public class TbInvUserreqDetail implements Serializable {
    //... Others field ...

    @Column(name = "allowedfractional")
    private Boolean allowedFractional = false;

    @Column(name = "qty")
    @NotNull(message = "Qty can't empty.")
    private double qty;

    //... setter getter ...
}

This is snipset of custom validator 'AllowFractional' interface:

@Target({ElementType.METHOD, ElementType.TYPE, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = AllowFractionalValidator.class)
@Documented
public @interface AllowFractional {
    String message() default "{default message}";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
    String allowedStateProperty();      
    String valueProperty();    

    @Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @interface List {
        AllowFractional[] value();
    }
}

This is the implemented validator class:

public class AllowFractionalValidator implements ConstraintValidator<AllowFractional, Object> {
    private String allowedStateProperty;
    private String valueProperty;
    private String msg;

    @Override
    public void initialize(AllowFractional a) {
        this.allowedStateProperty = a.allowedStateProperty();
        this.valueProperty = a.valueProperty();
        this.msg = a.message();
    }

    @Override
    public boolean isValid(Object obj, ConstraintValidatorContext context) {
        try {
            Boolean allowedState = Boolean.valueOf(BeanUtils.getProperty(obj, this.allowedStateProperty));
            Double value = Double.valueOf(BeanUtils.getProperty(obj, this.valueProperty));

            if (allowedState) {
                return true;
            } else {
                Double fractionalPart = value % 1;
                Double integralPart = value - fractionalPart;
                if (Double.compare(0d, fractionalPart) >= 0) {
                    return true;
                } else {
                    context.disableDefaultConstraintViolation();
                    context.buildConstraintViolationWithTemplate(msg).addPropertyNode(valueProperty)
                            .addConstraintViolation();
                    return false;
                }
            }
        } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException ex) {
            Logger.getLogger(AllowFractionalValidator.class.getName()).log(Level.SEVERE, null, ex);
            context.disableDefaultConstraintViolation();
            context.buildConstraintViolationWithTemplate(msg).addPropertyNode(valueProperty)
                    .addConstraintViolation();
            return false;
        }
    }
}

Hibernate validator class level constraint just work fine, and when running the application, Zk general error popup appears :

Validation failed for classes [com.myproject.entity.inv.table.TbInvUserreqDetail] during update time for groups [javax.validation.groups.Default, ] List of constraint violations:[ ConstraintViolationImpl{interpolatedMessage='Qty can't have fractional', propertyPath=qty, rootBeanClass=class com.myproject.entity.inv.table.TbInvUserreqDetail, messageTemplate='Qty can't have fractional'} ]

Could it return the constraint error to ibQty component's errorMessage? Thank you.

Support Options
  • Email Support
  • Training
  • Consulting
  • Outsourcing
Learn More