2

I am moving .net project to Spring Boot. So the question is on how to properly validate Integer fields in Spring. I have an entity with an Integer field:

@Entity
@Table(name = "tb_employee")
public class EmployeeDev {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "empl_id")
    private int emplId;
        
    @Range(min = 10, max = 50, message="Numbers only between 10 and 50")
    @Column(name = "default_vacation_days", nullable = true)
    private Integer defaultVacationDays;

... and a controller capturing the errors:

// update employee
    @PostMapping("/edit")
    public String showFormForUpdate(@Valid @ModelAttribute("employee") EmployeeDev employee, Errors errors,
            RedirectAttributes redirectAttributes,
            Model theModel) {

        if (null != errors && errors.getErrorCount() > 0) {
            
            List<ObjectError> errs = errors.getAllErrors();
            String errMsg = "";
            
            for (ObjectError e :errs)
                errMsg += e.getDefaultMessage();
            
            
            theModel.addAttribute("message", "Employee Edit failed. " + errMsg  );
            theModel.addAttribute("alertClass", "alert-danger");
            return "employeesdev/employee-form-edit";
        }

Now the problem is when I type into the default vacation days field any number outside of the range it shows the correct validation message: Numbers only between 10 and 50.

However if I try to insert something like 1A (possible user typo) I get this message: Failed to convert property value of type java.lang.String to required type java.lang.Integer for property defaultVacationDays; nested exception is java.lang.NumberFormatException: For input string: "1A"

I understand this is the correct message but I hate to show a message like this to a user. I would prefer to show just "Numbers only between 10 and 50" instead of data type conversion problems. Why bother users with Java data types?

I would appreciate any suggestions.

1
  • From which library @Range is taken? Commented Mar 3, 2021 at 18:59

1 Answer 1

1

If you want get custom behaviour from the annotation you need to define your own constriant annotation and validator for this annotation.

Here is basic example of custom constraint annotation:

@Target({TYPE, ANNOTATION_TYPE})
@Retention(RUNTIME)
@Constraint(validatedBy = CheckCalculationTypeValidator.class)
@Documented
public @interface CheckCalculationType {

   String message() default "calculation_type shall be not NULL if status = active";

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

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

and validator:

    public class CheckCalculationTypeValidator implements ConstraintValidator<CheckCalculationType, RequestDto> {

    @Override
    public boolean isValid(RequestDto dto, ConstraintValidatorContext constraintValidatorContext) {
        if (dto == null) {
            return true;
        }
        return !(Status.ACTIVE.equals(dto.getStatus()) && dto.getCalculationType() == null);
    }

    @Override
    public void initialize(CheckCalculationType constraintAnnotation) {
        // NOP
    }
}

Required dependency for Hibernate Validator:

<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.0.2.Final</version>
</dependency>
Sign up to request clarification or add additional context in comments.

4 Comments

I cannot find any custom validation example validating Integer fields. Everybody is doing a simple String validation.
If on the form a user puts wrong input like "1A" into an Integer field it comes back to Controller as null. So there is nothing to validate.
You should implement your validation logic inside isValid method, e.g. Integer.parseInt(myString), if NumberFormatException is thrown, then return false. If you have Integer type as input you can't handle other types - that is the reason of NumberFormatException. In your case you need change the input type from Integer to String.
Andrey, thank you for your input. I think you are correct I have to change input type from Integer to String. This way I can use Validator. When Integer is the input type the data type conversion exception happens event before any validation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.