2011-01-17 11 views
30

Tengo un controlador de resorte 3 con un validador para uno de los métodos. Insiste en validar cada objeto en el modelo. ¿Alguien podría explicarme por qué hace esto o si estoy haciendo algo mal?¿Por qué mi validador de Spring 3 lo valida todo en el modelo?

De acuerdo con la documentación, 5.7.4.3 Configuración de un validador de JSR-303 para su uso por Spring MVC (http://static.springsource.org/spring/docs/3.0.0.RC3/spring-framework-reference/html/ch05s07.html)

Con JSR-303, una única instancia javax.validation.Validator típicamente valida todos los objetos del modelo que declara restricciones de validación Para configurar un Validador respaldado por JSR-303 con Spring MVC, simplemente agregue un Proveedor JSR-303, como Hibernate Validator, a su classpath. Spring MVC lo detectará y habilitará automáticamente el soporte JSR-303 en todos los Controladores.

Ejemplo:

@Controller 
public class WhaleController { 

     @Autowired 
     private Validator myValidator; 

     @Autowired 
     private WhaleService whaleService; 

     @InitBinder 
     protected void initBinder(WebDataBinder binder) { 
       binder.setValidator(this.myValidator); 
     } 

     @RequestMapping(value="/save-the-whales") 
     @Transactional 
     public void saveTheWhales(@Valid WhaleFormData formData, BindingResult errors, Model model) { 
       if (!errors.hasFieldErrors()) { 
         Whale whale = new Whale(); 

         whale.setBreed(formData.getBreed()); 

         this.whaleService.saveWhale(whale); 

         model.addAttribute("whale", whale); 

       } 
       model.addAttribute("errors", errors.getFieldErrors()); 
     } 

} 

Cuando ejecute se quejan de que la ballena es un blanco válido para miValidador (que se fija para validar WhaleFormData, y lo hace muy bien). Whale es un POJO sin restricciones de validación, anotación y ninguna configuración en ninguna parte. A través del método de prueba y error, he encontrado que CUALQUIER objeto colocado en el modelo intentará ser validado y fallará si el validador no está configurado para manejarlo. Los primitivos están bien.

¿Alguien me puede decir por qué es así, señalarme la documentación adecuada y/o decirme la mejor manera de poner algo en el modelo sin tener que validarlo?

En el caso anterior me gustaría colocar "ballena" en el modelo ya que ahora tendrá un whaleId único() que recibió de mi capa de persistencia.

Gracias!

Respuesta

48

Supongo que este comportamiento no está cubierto en la documentación.

El problema es causado por lo siguiente:

  1. Por defecto, @InitBinder método -annotated se llama para cada atributo no-modelo primitivo, tanto entrante como saliente (el propósito de llamar por outcoming attibutes se para permitirle registrar PropertyEditor s personalizados, que las etiquetas de formulario utilizan al procesar un formulario).

  2. DataBinder.setValidator() contiene una marca de verificación defensiva que llama a Validator.supports() y arroja una excepción si se devuelve false. Por lo tanto, no hay ningún intento de realizar una validación, solo un control anticipado.

La solución es restringir el alcance de @InitBinder a determinados atributos:

@InitBinder("whaleFormData") 
protected void initBinder(WebDataBinder binder) { ... } 
+19

En vista de ello, ¿cuál es el propósito de la '@ Valid' atribuir? – rakslice

+1

Funciona gracias. Me preguntaba: ¿se tratan las colecciones de una manera especial? ¿Por qué si agrego una recopilación al modelo, para mostrar los valores dentro de un menú desplegable, el error no ocurre? – Ena

Cuestiones relacionadas