Validating double and floating values ​​with Hibernate Validator - bean validation

I am looking for a way to check the java.lang.Double field in a Spring bean command for its maximum and minimum values ​​(the value must lie between a given range of values), for example

 public final class WeightBean { @Max(groups={ValidationGroup.class}, value=Double.MAX_VALUE, message="some key or default message") @Min(groups={ValidationGroup.class}, value=1D, message="some key or default message") private Double txtWeight; //Getter and setter. public interface ValidationGroup{} } 

But both @Max and @Min cannot take the value java.lang.Double .

Please note that double and float are not supported due to rounding errors (some providers may provide some approximate support)

So what is the way to check for such fields?

I am working with Spring 3.2.0 and Hibernate Validator 4.3.1 CR1.

+11
source share
6 answers

You can use annotation, but you can get false results. This is a common problem with doubling and imo in many cases. Double_s should be avoided. Maybe switching to another type is the best solution? For example, BigDecimal?

+8
source

If you switched to BigDecimal (or BigInteger), you can use @DecimalMin or @DecimalMax . But this is still not a solution for float or double.

+6
source

I avoided the double and float types and implemented a special validator that could check the BigDecimal value based on accuracy and scale.

Descriptor restrictions.

 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) @Documented public @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; } 

Validator of restrictions.

 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 can be extended to other types when necessary.


Finally, in a bean, a property of type BigDecimal can be annotated with the annotation @BigDecimalRange 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 {} } 
+4
source

This is sometimes convenient when paired with @AssertTrue / @AssertFalse from javax.validation.constraints

 public final class WeightBean { @NotNull private Double txtWeight; //Getter and setter. @AssertTrue public boolean getTxtWeightCheck() { return txtWeight > 0.1 && txtWeight < 0.9; } } 
+1
source

You can also use @Digits in the hibernation test API

 @Digits(integer = 10 /*precision*/, fraction = 2 /*scale*/) 
0
source

Newer versions of the Hibernate Validator (at least 6.0.17) support @DecimalMin/Max annotation for double

See class for validation.

0
source

All Articles