2012-10-01 15 views
9

カスタム制約バリデーター内でBeanオートワイヤーに問題があります。制約バリデータインスタンスは、SpringのLocalValidatorFactoryBeanを使用して指定されていません。 JSR-303プロバイダは、ハイバネート・バリデータ4.2.0.Finalです。Spring 3.1カスタム制約バリデーター内でオートワイヤリングが機能しない

Spring構成抜粋:

<!-- JSR 303 validation --> 
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" /> 
<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor"/> 

カスタム制約バリ:

import javax.validation.ConstraintValidator; 
import javax.validation.ConstraintValidatorContext; 

import org.springframework.beans.factory.annotation.Autowired; 

import com.model.Subject; 
import com.services.SomeTypeService; 

public class ReadOnlyValidator implements ConstraintValidator<ReadOnly, String> { 

@Autowired 
private SomeTypeService someTypeService; 

@Override 
public void initialize(ReadOnly constraintAnnotation) { } 

@Override 
public boolean isValid(String type, ConstraintValidatorContext context) { 
    try { 
     if (null != type) { 
         return !someTypeService.isReadonly(type); 
        } 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 

    return false; 
} 
} 

注釈:

import static java.lang.annotation.ElementType.*; 
import static java.lang.annotation.RetentionPolicy.*; 

import java.lang.annotation.Documented; 
import java.lang.annotation.Retention; 
import java.lang.annotation.Target; 

import javax.validation.Constraint; 
import javax.validation.Payload; 

@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER }) 
@Retention(RUNTIME) 
@Constraint(validatedBy = ReadOnlyValidator.class) 
@Documented 
public @interface ReadOnly { 
String message() default "{constraints.subjecttype.readonly}"; 
public abstract Class<?>[] groups() default {}; 
public abstract Class<? extends Payload>[] payload() default {}; 
} 

SomeService:

@Validated 
public interface SomeService { 
    ... 
    public void updateType(@ReadOnly String type) throws SomeException; 
    ... 
} 

SomeServiceImpl:

@Service 
public class SomeServiceImpl implements SomeService { 
    ... 
    public void updateType(String type) throws SomeException { 
    // do something 
    } 
    ... 
} 

SomeTypeServiceがSomeServiceに依存しない別の@Service注釈付きBeanです...

問題はオートワイヤリングが動作しないように私は、NPEを得るということです。他の誰かがカスタムバリデータインスタンスを管理していますが、Springではなく、カスタムバリデータインスタンスを管理しています。

アドバイスはありません。

+0

質問Claudiu - サービスメソッドのレベルで@validatedがあるため、ContextLoaderListenerとDispatcherServletで宣言された2つの異なるアプリケーションコンテキストがありますか?ルートWebアプリケーションコンテキストでLocalValidatorFactoryBeanも宣言する必要がありますか? –

+0

さて、私はLocalValidatorFactoryBeanインスタンスの数に関連するいくつかの異常が見つかりました。 「質問」の記述で与えた宣言は、service-content.xml =>にあります。これは1つのインスタンスです。 =>あなたがルートWebアプリケーションを持っていることが正しいなら、自動的に別のインスタンスが作成されます。 –

+0

LocalValidatorFactoryBeanインスタンスが1つしか作成されていないことを確認した後、作成されたReadOnlyValidatorのインスタンス数を確認するために移動しました。 jmap -histo:live を使用しています。 grep "ReadOnlyValidator"、私は、インスタンスが1つしか作成されていないことに気付きましたが、初めてupdateTypeサービスメソッドが呼び出され、LocalValidatorFactBeanが初期化されていないときにのみ呼び出されます。私は、休止状態の検証エンジンは、単に独自の制約バリデータインスタンスを作成すると思います。どのようにBeanの配線を使用できるように、ReadOnlyValidatorのインスタンスを管理するためにLocalValidatorFactoryBeanを強制するのですか? –

答えて

9

問題が見つかりました。同一の "バリ" ビーン基準MethodValidationPostProcessorとMVCで使用されなければならない:アノテーション駆動型宣言:

サービスのcontext.xml

<!-- JSR 303 validation --> 
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/> 
<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor"> 
    <property name="validator" ref="validator"/> 
</bean> 
    ... 

ディスパッチャ-servlet.xml

... 
<mvc:annotation-driven validator="validator" /> 
... 
+0

Claudiu、これは、すべての新しいバリデーターをMethodValidationPostProcessorに登録する必要があることを意味しますか?これをJava Configで実装する方法を知っていますか?私は同じ問題を解消しています。唯一の違いは、私はInterfaceをautowiringしていて、xmlではなくJava Configを使用していることです。 – Tito

+0

ValidatorをMethodValidationPostProcessorに「注入」する必要がありました。 –

+0

dispatcher-servlet.xmlに定義されているBeanのLocalValidatorFactoryBeanおよびMethodValidationPostProcessorが@Validatedで動作しない場合。 – Bodil

4

Tito、Javaの設定で以下のようなものを使用できるかどうか確認してください:

@Configuration 
public class SampleConfig { 
    ... 

    @Bean 
    public Validator validator() { 
    return new LocalValidatorFactoryBean().getValidator(); 
    } 

    @Bean 
    public MethodValidationPostProcessor mvpp() { 
    MethodValidationPostProcessor mvpp = new MethodValidationPostProcessor(); 
    mvpp.setValidator(validator()); 

    return mvpp; 
    } 

    ... 
} 

別の構成BeanでバリデーターBeanを再利用するには、@Importアノテーションを使用できます。

関連する問題