2016-04-05 1 views
1

プロパティの標準javax.validationと機能検証のための独自の検証を使いたいと思います。単純化されたサブクラスは以下のようになります。ベースクラスでjavax.validation(JSR303)を使用するにはどうすればよいですか?

public class TestData extends AbstractData { 
    @NotNull 
    Long id = null; 

    @NotNull 
    Long value = null; 

    public Set<ConstraintViolation<TestData>> validateFunctional() { 
    Set<ConstraintViolation<TestData>> violations = new HashSet<>(); 
    if (id < 42 || value > 4711) { 
     //--- here comes another question: how do I create a constraint violation? 
    } 
    return violations; 
    } 
} 

これは、基本クラスである:

public abstract class AbstractData { 
    public Set<ConstraintViolation<?>> validate() { 
    //--- First validate single properties 
    Set<ConstraintViolation<?>> violations = validator.validate(this); 
    } 
    //--- Single props OK => validate functional 
    if (violations.isEmpty()) { 
    violations.add(validateFunctional()); 
    } 
    return violations; 
} 

はエラーに

型の不一致を与える:セットする> AbstractData > ConstraintViolation <セット<から変換することはできません<制約違反<? > >

+0

コンパイラがジェネリック型を推論する方法はありません。 – dambros

+0

あなたは正しいです。コンパイラはAbstractDataから?に変換できません。しかし、この疑似型安全をどうやって取り除くことができますか? Validator.validateというインタフェースはひどく設計されているようです。または私はそれを得ることはありません... –

答えて

0

私は、これはあなたが探しているものであるべきと考えている:検証する

public abstract class AbstractData<T> { 

    abstract T getObj(); 

    public Set<ConstraintViolation<T>> isValid(){ 
    //do your custom validations if needed 
    return Validation.buildDefaultValidatorFactory() 
      .getValidator().validate(getObj()); 
    } 
} 

はPOJO:

public class Bar extends AbstractData<Bar> { 
    @NotNull 
    private Long id; 

    @NotNull 
    private Long value; 

    @CustomConstraint 
    private Long customConstraint; 

    @Override 
    public Bar getObj() { 
     return this; 
    } 
} 

そして、単にbar.isValid()を呼び出します。

編集:私は@CustomConstraintとロングフィールドに注釈を付けると値を渡した場合、この例では

@Constraint(validatedBy = {CustomConstraint.CustomConstraintValidator.class}) 
@Target({ElementType.FIELD, ElementType.PARAMETER}) 
@Retention(value = RetentionPolicy.RUNTIME) 
@Documented 
public @interface CustomConstraint { 

    String message() default "Invalid value"; 

    Class<?>[] groups() default {}; 

    Class<? extends Payload>[] payload() default {}; 

    class CustomConstraintValidator implements ConstraintValidator<CustomConstraint, Long> { 

     @Override 
     public void initialize(CustomConstraint customConstraint) { 

     } 

     @Override 
     public boolean isValid(Long obj, ConstraintValidatorContext constraintValidatorContext) { 
      if (obj == null) 
       return false; 

      if (obj < 10) 
       return false; 

      return true; 
     } 
    } 
} 

:カスタム制約に関するご質問については

、あなたはこのようにそれを行うことができます10未満またはnullの場合、バリデータはエラーを返し、そうでない場合はエラーを返します。この例では、検証自体は役に立たず、私はちょうどあなたのものを構築するためのスニペットとして役立つものを用意しています。

+0

興味深いアプローチ。しかし、カスタムバリデーションはサブクラスにあり、ベースクラスにはありません。 validator.validateで本当に奇妙なジェネリックスを克服するには、サブクラスを独自の基本クラスに渡して、 "this"を返すメソッド "abstract T getObj()"が必要です。私はこのJSRが利用可能になるアップデートを得ることを本当に願っています。私はカスタムバリデーターを探しているのではなく、いくつかのコードで違反のセットに追加できる制約違反を簡単に作成するためのコードを探しています。 –

+0

'validate()'の実装方法が間違っているわけではないので、ここではジェネリック全体を誤解していると思います。 – dambros

+0

それは間違っていません。何のメリットも無く唯一不必要に複雑です。 validate()の最初のパラメータは、検証するbeanです。だからクラスを知っている。この擬似型の安全性の必要はありません。あなたのソリューションは、これに準拠するためにゲッターをベースクラスに追加することを提案しました。 –

関連する問題