Validating double and float values using Hibernate Validator - bean validation
You can use the annotation, but you might get false results depending. This is a general problem with doubles and imo in many cases _Double_s should be avoided. Maybe switching to a different type is the best solution? BigDecimal for example?
If you have switched to BigDecimal (or BigInteger), you could use @DecimalMin or @DecimalMax.But this is still no solution for float or double.
I have avoided the double
and the float
types and implemented a custom validator that could validate a BigDecimal
value based on the precision and the scale.
The constraint descriptor.
package constraintdescriptor;import constraintvalidator.BigDecimalRangeValidator;import java.lang.annotation.Documented;import static java.lang.annotation.ElementType.ANNOTATION_TYPE;import static java.lang.annotation.ElementType.FIELD;import static java.lang.annotation.ElementType.METHOD;import java.lang.annotation.Retention;import static java.lang.annotation.RetentionPolicy.RUNTIME;import java.lang.annotation.Target;import javax.validation.Constraint;import javax.validation.Payload;@Target({METHOD, FIELD, ANNOTATION_TYPE})@Retention(RUNTIME)@Constraint(validatedBy = BigDecimalRangeValidator.class)@Documentedpublic @interface BigDecimalRange { public String message() default "{java.math.BigDecimal.range.error}"; public Class<?>[] groups() default {}; public Class<? extends Payload>[] payload() default {}; long minPrecision() default Long.MIN_VALUE; long maxPrecision() default Long.MAX_VALUE; int scale() default 0;}
The constraint validator.
package constraintvalidator;import constraintdescriptor.BigDecimalRange;import java.math.BigDecimal;import javax.validation.ConstraintValidator;import javax.validation.ConstraintValidatorContext;public final class BigDecimalRangeValidator implements ConstraintValidator<BigDecimalRange, Object> { private long maxPrecision; private long minPrecision; private int scale; @Override public void initialize(final BigDecimalRange bigDecimalRange) { maxPrecision = bigDecimalRange.maxPrecision(); minPrecision = bigDecimalRange.minPrecision(); scale = bigDecimalRange.scale(); } @Override public boolean isValid(final Object object, final ConstraintValidatorContext cvc) { boolean isValid = false; if (object == null) { // This should be validated by the not null validator (@NotNull). isValid = true; } else if (object instanceof BigDecimal) { BigDecimal bigDecimal = new BigDecimal(object.toString()); int actualPrecision = bigDecimal.precision(); int actualScale = bigDecimal.scale(); isValid = actualPrecision >= minPrecision && actualPrecision <= maxPrecision && actualScale <= scale; if (!isValid) { cvc.disableDefaultConstraintViolation(); cvc.buildConstraintViolationWithTemplate("Precision expected (minimun : " + minPrecision + ", maximum : " + maxPrecision + "). Maximum scale expected : " + scale + ". Found precision : " + actualPrecision + ", scale : " + actualScale).addConstraintViolation(); } } return isValid; }}
This could be extended for other types as well, as and when required.
And finally in the bean, the property of the type BigDecimal
could be annotated by the @BigDecimalRange
annotation as follows.
package validatorbeans;public final class WeightBean { @BigDecimalRange(minPrecision = 1, maxPrecision = 33, scale = 2, groups = {ValidationGroup.class}, message = "The precision and the scale should be less than or equal to 35 and 2 respectively.") private BigDecimal txtWeight; // Getter and setter. public interface ValidationGroup {}}