Qué configuración es necesaria para el uso de anotaciones de javax.validation.constraints como @Size, @NotNull, etc.? Aquí está mi código:

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

public class Person {
      @NotNull
      private String id;

      @Size(max = 3)
      private String name;

      private int age;

      public Person(String id, String name, int age) {
        this.id = id;
        this.name = name;
        this.age = age;
      }
}

Cuando trato de usarlo en otra clase, la validación no funciona (es decir, el objeto es creado sin error):

Person P = new Person(null, "Richard3", 8229));

¿Por qué no esta de aplicar restricciones para id y name? ¿Qué más tengo que hacer?

  • No funciona por arte de magia, usted necesita para configurar un validador. Lo que el contexto es de este código que se ejecuta en?

10 Comentarios

  1. 49

    Para JSR-303 bean validation a trabajar en la Primavera, se necesitan varias cosas:

    1. MVC configuración de espacio de nombres para anotaciones: <mvc:annotation-driven />
    2. La JSR-303 especificaciones JAR: validation-api-1.0.0.GA.jar (parece que)
    3. Una implementación de la especificación, como la Hibernación de Validación, que parece ser la más comúnmente usada ejemplo: hibernate-validator-4.1.0.Final.jar
    4. En el bean para ser validado, la validación de las anotaciones, ya sea a partir de la especificación del FRASCO o de la aplicación JAR (que ya lo ha hecho)
    5. En el controlador que desea validar, anotar el objeto que desea validar con @Valid, y, a continuación, incluir una BindingResult en la firma del método para la captura de los errores.

    Ejemplo:

    @RequestMapping("handler.do")
    public String myHandler(@Valid @ModelAttribute("form") SomeFormBean myForm, BindingResult result, Model model) {
        if(result.hasErrors()) {
          ...your error handling...
        } else {
          ...your non-error handling....
        }
    }
    • Esto nos provee con la configuración por defecto del validador. Ahora, me gustaría configurar el validador antes de ser utilizados. Donde puedo configurarlo ? Cualquier sobrescribir para implementar o setter llamar ?
    • El problema que he experimentado fue, no me di cuenta de que tenía que añadir @Valid a cada uno de los miembros de la variable, que fue también un objeto que contenía restricciones de validación.
    • He añadido @Válido para mi RequestBody pero aún así la restricción no se invoca. He revisado las dependencias, en caso de conflicto. Se ha solucionado así. No estoy seguro de lo que problema es. También he comprobado de que hay anotación aplicado al campo. Es aplicado.
    • Curiosamente también tengo todos los puntos mencionados anteriormente cumplido. Todavía la validación no funciona 🙁
  2. 28

    Debe utilizar el Validador de comprobar si la clase es válida.

    Person person = ....;
    ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
    validator = factory.getValidator();
    Set<ConstraintViolation<Person>> violations = validator.validate(person);

    Entonces, la iteración de las violaciones establecidas, se puede encontrar violaciones.

    • Creo que, esto es perfectamente respondió con independencia de marco que se utiliza. gracias.. pero tengo una duda, ¿cómo podemos validar un parámetro que se pasa a algún método en el contexto de sin ningún tipo de marco. por ejemplo,test(@NotNull String str), podemos escribir validador para el mismo ?
  3. 5

    Que tendría que llamar a un Validador en la Entidad, si se quiere validar. Entonces usted va a obtener un conjunto de ConstraintViolationException, que básicamente para mostrar que el campo/s de su Entidad, no es una violación de la restricción y qué fue exactamente lo. Tal vez usted puede también compartir algunos de los códigos de espera para validar su entidad.

    Que a menudo se utiliza la técnica es hacer la validación en @PrePersist y rollback de la transacción si el uso de múltiples modificaciones de datos durante la transacción o hacer otras acciones cuando obtenga una excepción de validación.

    El código debe ir así:

    @PrePersist
    public void prePersist(SomeEntity someEntity){
        Validator validator = Validation.buildDefaultValidatorFactory.getValidator();
        Set<ConstraintViolation<SomeEntity>> = validator.validate(someEntity);
        //do stuff with them, like notify client what was the wrong field, log them, or, if empty, be happy
    }
  4. 1

    en mi caso he tenido una clase personalizada de nivel de restricción que no fue llamado.

    @CustomValidation //not called
    public class MyClass {
        @Lob
        @Column(nullable = false)
        private String name;
    }

    tan pronto como he añadido un campo de nivel de restricción de mi clase, ya sea estándar o personalizado, el nivel de restricción de comenzar a trabajar.

    @CustomValidation //now it works. super.
    public class MyClass {
        @Lob
        @Column(nullable = false)
        @NotBlank //adding this made @CustomValidation start working
        private String name;
    }

    parece buggy comportamiento para mí, pero lo suficientemente fácil como para evitar supongo

  5. 1

    Vengo aquí a algunos años después, y pude solucionarlo gracias a atrain‘s comentario de arriba. En mi caso, me faltaba @Valid en el API que recibe el Objeto (POJO en mi caso) que fue anotado con @Size. Se solucionó el problema.

    Hice no necesario añadir ningún extra anotación, tales como @Valid o @NotBlank a la variable anotado con @Size, sólo que la restricción en la variable y lo que he mencionado en el API…

    Clase Pojo:

    ...
    @Size(min = MIN_LENGTH, max = MAX_LENGTH);
    private String exampleVar;
    ...

    De la API de la Clase:

    ...
    public void exampleApiCall(@RequestBody @Valid PojoObject pojoObject){
      ...
    }

    Gracias y saludos

  6. 0

    Necesita agregar @Válido a cada uno de los miembros de la variable, que fue también un objeto que contenía restricciones de validación.

  7. 0

    Para que @Válido en servicio, la interfaz de trabajo sólo para ese objeto. Si usted tiene más de validaciones dentro de la jerarquía de ServiceRequest objeto, entonces usted podría tener explícitamente gatillo validaciones. Así es como lo he hecho:

    public class ServiceRequestValidator {
    
          private static Validator validator;
    
          @PostConstruct
          public void init(){
             validator = Validation.buildDefaultValidatorFactory().getValidator();
          }
    
          public static <T> void validate(T t){
            Set<ConstraintViolation<T>> errors = validator.validate(t);
            if(CollectionUtils.isNotEmpty(errors)){
              throw new ConstraintViolationException(errors);
            }
         }
    
    }

    Usted necesita tener siguientes anotaciones en el nivel de objeto si desea activar la validación para ese objeto.

    @Valid
    @NotNull
    • Se mezcla instancia y campos estáticos… Horrible práctica…
  8. 0

    para los parámetros del método se pueden utilizar Objetos.requireNonNull() como este:
    test(String str) {
    Objects.requireNonNull(str);
    }

    Pero esto es sólo comprueba en tiempo de ejecución y que se genere un NPE si es null. Es como una de las condiciones previas de verificación. Pero eso podría ser lo que usted está buscando.

  9. 0

    Gran respuesta de atrain,
    pero tal vez la mejor solución para la captura de excepciones es utilizar propia HandlerExceptionResolver
    y coger

    @Override
    public ModelAndView resolveException(
        HttpServletRequest aReq, 
        HttpServletResponse aRes,
        Object aHandler, 
        Exception anExc
    ){
        //....
        if(anExc instanceof MethodArgumentNotValidException) //do your handle     error here
    }

    Entonces usted es capaz de mantener su controlador de tan limpia como sea posible.
    Usted no necesita BindingResult, Modelo y SomeFormBean en myHandlerMethod más.

Dejar respuesta

Please enter your comment!
Please enter your name here