Estoy moviendo el proyecto .net a Spring Boot. Entonces, la pregunta es cómo validar correctamente los campos Integer en Spring. Tengo una entidad con un campo Integer:

@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;

... y un controlador que captura los errores:

// 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";
        }

Ahora, el problema es que cuando escribo en el campo de días de vacaciones predeterminado cualquier número fuera del rango, muestra el mensaje de validación correcto: Números solo entre 10 y 50.

Sin embargo, si intento insertar algo como 1A (posible error tipográfico del usuario), aparece este mensaje: No se pudo convertir el valor de propiedad del tipo java.lang.String al tipo requerido java.lang.Integer para la propiedad defaultVacationDays; La excepción anidada es java.lang.NumberFormatException: para la cadena de entrada: "1A"

Entiendo que este es el mensaje correcto, pero odio mostrar un mensaje como este a un usuario. Preferiría mostrar solo "Números solo entre 10 y 50" en lugar de problemas de conversión de tipos de datos. ¿Por qué molestar a los usuarios con los tipos de datos de Java?

Apreciaria cualquier sugerencia.

2
Michael Bee 3 mar. 2021 a las 21:14

1 respuesta

La mejor respuesta

Si desea obtener un comportamiento personalizado de la anotación, debe definir su propia anotación constriant y validador para esta anotación.

A continuación, se muestra un ejemplo básico de anotación de restricción personalizada:

@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 {};
}

Y validador :

    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
    }
}

Dependencia requerida para Hibernate Validator:

<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.0.2.Final</version>
</dependency>
1
Andrey 3 mar. 2021 a las 19:11