2011-04-20 13 views
4

私は、Spring MVCを使用してフォームのJSR-303検証をセットアップしようとしています。私はすべて正しく構成されていた(少なくとも私がやったと思う)、検証は大部分が正しく機能している。しかし、私が検証したいオブジェクトのコレクションを含むコマンドオブジェクトを持っていて、そのコレクションに@Validを付けると、Hibernate JSR-303プロバイダは正しいpropertyPathを提供していません。 ContraintViolationオブジェクト内のpropertyPathはlist[0].barlist[1].barのように設定する必要がありますが、Hibernateバリデーターは単にlist[].barlist[].barを提供しています。これにより、SpringのSpringValidatorAdaptor.validate()メソッドがフィールドレベルのエラーを追加しようとしたときにNumberFormatExceptionが発生します(内部的にこれらの大括弧内に数値が存在することが予想されるため)。Hibernate JSR303検証と誤って生成されたpropertyPath

spring-context-3.0.5とhibernate-validator-4.1.0.Final(私も4.0.2.GAと4.2.0.Beta2を試して同じ結果を得ました)を使用して、私は小さなユニットテストを書いています問題を説明するために:

package com.foo; 

import java.util.ArrayList; 
import java.util.Collection; 
import java.util.Set; 

import javax.validation.ConstraintViolation; 
import javax.validation.Valid; 
import javax.validation.Validation; 
import javax.validation.Validator; 

import org.hibernate.validator.constraints.NotEmpty; 
import org.junit.Test; 
import org.springframework.util.AutoPopulatingList; 

public class ValidatorTest { 

    class Person { 
     @NotEmpty 
     private String name; 

     @NotEmpty 
     @Valid 
     private Collection<Foo> list = new AutoPopulatingList<Foo>(Foo.class); 

     public void setName(String name) { 
      this.name = name; 
     } 

     public String getName() { 
      return name; 
     } 

     public Collection<Foo> getList() { 
      return list; 
     } 

     public void setList(Collection<Foo> foos) { 
      this.list = foos; 
     } 
    } 

    class Foo { 
     @NotEmpty 
     private String bar; 

     public void setBar(String bar) { 
      this.bar = bar; 
     } 

     public String getBar() { 
      return bar; 
     } 
    } 

    @Test 
    public void testValidator() throws Exception { 
     Foo foo0 = new Foo(); 
     foo0.setBar(""); 

     Foo foo1 = new Foo(); 
     foo1.setBar(""); 

     Collection<Foo> list = new ArrayList<ValidatorTest.Foo>(); 
     list.add(foo0); 
     list.add(foo1); 

     Person person = new Person(); 
     person.setName("Test Person"); 
     person.setList(list); 

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

     for (ConstraintViolation<Person> constraintViolation : violations) { 
      System.out.println(constraintViolation); 
     } 
    } 
} 

を上記試験は、以下の出力を生成する:

ConstraintViolationImpl{interpolatedMessage='may not be empty', propertyPath=list[].bar, rootBeanClass=class com.foo.ValidatorTest$Person, messageTemplate='{org.hibernate.validator.constraints.NotEmpty.message}'} 
ConstraintViolationImpl{interpolatedMessage='may not be empty', propertyPath=list[].bar, rootBeanClass=class com.foo.ValidatorTest$Person, messageTemplate='{org.hibernate.validator.constraints.NotEmpty.message}'} 

それが生成するエラーは正しいです。しかし、propertyPathは(少なくとも私が理解しているものから)ではありません。

ここで、HibernateのJSR-303実装をApache(org.apache.bval.bundle-0.2-incubating - 依存関係をhereとしています)に置き換えると、期待通りの結果が得られます。これはまったく同じテストですが、Hibernateの代わりにApacheのJSR-303アノテーションを使用しています。今のPropertyPathフィールドに存在するインデックスを注意:様々な理由

ConstraintViolationImpl{[email protected], propertyPath='list[0].bar', message='may not be empty', [email protected], value=} 
ConstraintViolationImpl{[email protected], propertyPath='list[1].bar', message='may not be empty', [email protected], value=} 

、私はおそらくHibernateのJSR-303の実装を使用して立ち往生しています。 Hibernateバリデーターがそれらのインデックスに値を設定しない原因となっている何かがありますか?私は可能な限り私のSpringコントローラで手動エラー処理をしないようにしています。

ご協力いただきありがとうございます。

答えて

5

私はHibernate forumsでこの質問をしました。そこには回答がありました。他の誰かがこの問題に遭遇した場合に、私はここで答えを共有したかったのです。

コレクションをリストに変更するだけで問題は解決します。ここでは、更新ユニットテストです:

package com.foo; 

import java.util.ArrayList; 
import java.util.List; 
import java.util.Set; 

import javax.validation.ConstraintViolation; 
import javax.validation.Valid; 
import javax.validation.Validation; 
import javax.validation.Validator; 

import org.hibernate.validator.constraints.NotEmpty; 
import org.junit.Test; 
import org.springframework.util.AutoPopulatingList; 

public class ValidatorTest { 

    class Person { 
     @NotEmpty 
     private String name; 

     @NotEmpty 
     @Valid 
     private List<Foo> list = new AutoPopulatingList<Foo>(Foo.class); 

     public void setName(String name) { 
      this.name = name; 
     } 

     public String getName() { 
      return name; 
     } 

     public List<Foo> getList() { 
      return list; 
     } 

     public void setList(List<Foo> foos) { 
      this.list = foos; 
     } 
    } 

    class Foo { 
     @NotEmpty 
     private String bar; 

     public void setBar(String bar) { 
      this.bar = bar; 
     } 

     public String getBar() { 
      return bar; 
     } 
    } 

    @Test 
    public void testValidator() throws Exception { 
     Foo foo0 = new Foo(); 
     foo0.setBar(""); 

     Foo foo1 = new Foo(); 
     foo1.setBar(""); 

     List<Foo> list = new ArrayList<ValidatorTest.Foo>(); 
     list.add(foo0); 
     list.add(foo1); 

     Person person = new Person(); 
     person.setName("Test Person"); 
     person.setList(list); 

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

     for (ConstraintViolation<Person> constraintViolation : violations) { 
      System.out.println(constraintViolation); 
     } 
    } 
} 

そして(今のインデックスを含みます)上記のテストからの出力:

ConstraintViolationImpl{interpolatedMessage='may not be empty', propertyPath=list[1].bar, rootBeanClass=class com.foo.ValidatorTest$Person, messageTemplate='{org.hibernate.validator.constraints.NotEmpty.message}'} 
ConstraintViolationImpl{interpolatedMessage='may not be empty', propertyPath=list[0].bar, rootBeanClass=class com.foo.ValidatorTest$Person, messageTemplate='{org.hibernate.validator.constraints.NotEmpty.message}'} 
関連する問題